【Day30】卡码网:46. 携带研究材料,LeetCode:416. 分割等和子集

文章目录

卡码网:46. 携带研究材料

https://kamacoder.com/problempage.php?pid=1046

0-1背包问题,二维

思路

  1. 定义:dp[i][j] 表示只考虑前 i 件物品(索引从 0i ),在背包容量为 j 时能获得的最大价值。最终目标为 dp[n-1][bag]
  2. 状态转移方程:
    (1)当 j < weight[i](当前容量放不下第 i 件物品)时:
    dp[i][j] = dp[i-1][j] ,即不选第 i 件,结果与前 i - 1 件相同。
    (2)当 j >= weight[i](可以放下第 i 件物品)时:
    dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])
    不选:价值为 dp[i-1][j]
    选:先腾出 weight[i] 的空间( j - weight[i] ),加上第 i 件的价值。
  3. 初始化:所有 dp[i][j] 初始化为0。

解答

python 复制代码
first_line = input().split()
n = int(first_line[0])
bag = int(first_line[1])

second_line = input().split()
third_line = input().split()
weight = [int(x) for x in second_line]
value = [int(x) for x in third_line]

dp = [[0] * (bag + 1) for _ in range(n)]

for j in range(weight[0], bag + 1):
    dp[0][j] = value[0]

for i in range(1, n):
    for j in range(bag + 1):
        if j < weight[i]:
            dp[i][j] = dp[i - 1][j]
        else:
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

print(dp[n - 1][bag])

0-1背包问题,一维

思路

  1. 定义:dp[j] 表示当前考虑的物品范围内,背包容量为 j 时能获得的最大价值。
  2. 状态转移方程:dp[j] = max(dp[j], dp[j - w] + v) (j >= w)
  3. 初始化:dp = [0] * (bag + 1)

解答

python 复制代码
first_line = input().split()
n = int(first_line[0])
bag = int(first_line[1])

second_line = input().split()
third_line = input().split()
weight = [int(x) for x in second_line]
value = [int(x) for x in third_line]

dp = [0] * (bag + 1) # dp[j] 表示容量 j 能获得的最大价值

for i in range(n):
    w = weight[i]
    v = value[i]
    # 逆序遍历,保证每种物品只选一次
    for j in range(bag, w - 1, -1):
        dp[j] = max(dp[j], dp[j - w] + v)

print(dp[bag])

LeetCode:416. 分割等和子集

https://leetcode.cn/problems/partition-equal-subset-sum/description/
添加链接描述

思路

转化为01-背包问题:每个元素只能选或不选,背包容量为 target,求是否能恰好装满。

解答

python 复制代码
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        total = sum(nums)
        # 总和为奇数则无法平分
        if total % 2 != 0:
            return False
        
        target = total // 2
        n = len(nums)
        
        # dp[j] 表示当前已考虑的元素能否凑出和为 j
        dp = [False] * (target + 1)
        dp[0] = True
        
        for num in nums:
            # 从后往前更新,避免重复使用当前元素
            for j in range(target, num - 1, -1):
                dp[j] = dp[j] or dp[j - num]
        
        return dp[target]
相关推荐
2601_9620781914 小时前
Python中calendar.weekday用法
python·编程技巧·calendar·日期处理·weekday
2601_9622186114 小时前
万象生鲜系统业财一体化底层打通技术自动生成经营账单
大数据·数据库·人工智能·python·算法
2601_9669496514 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
2601_9628857214 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
吞下星星的少年·-·14 小时前
The 2026 ICPC Asia East Continent Online Contest (II)(构造)
数据结构·算法
李高钢14 小时前
Python FastAPI 框架入门:从零搭建你的第一个高性能 API 服务
数据库·python·fastapi
ocean210315 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文
Warson_L15 小时前
Python的OrderedDict
python
stolentime15 小时前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法