586 字
3 分钟
代码随想录算法训练营第三十天 | 动态规划 Part03

🎒 0-1 背包问题#

问题描述:给定物品重量和价值,背包容量为 n,每个物品只能选一次,求在容量不超限制的前提下最大价值。

  • 状态定义dp[i][j] 表示从前 i 个物品中选择、且总重量不超过 j 时的最大总价值。
  • 状态转移方程
    • 不选第 i 个物品:dp[i][j] = dp[i - 1][j]
    • 选第 i 个物品:dp[i][j] = dp[i - 1][j - weight[i]] + value[i](前提是 j >= weight[i]

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

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

二维解法#

import sys
input = sys.stdin.read
def main():
data = input().strip().split()
index = 0
m = int(data[index]) # 物品数量
index += 1
n = int(data[index]) # 背包容量
index += 1
weight = []
for i in range(m):
weight.append(int(data[index]))
index += 1
value = []
for i in range(m):
value.append(int(data[index]))
index += 1
# dp[i][j] 表示前 i 个物品,容量为 j 时的最大价值
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(n + 1):
if j < weight[i - 1]:
# 容量不足,不能选第 i 个物品
dp[i][j] = dp[i - 1][j]
else:
# 取选与不选两种方案的最大值
dp[i][j] = max(dp[i - 1][j],
dp[i - 1][j - weight[i - 1]] + value[i - 1])
print(dp[m][n])
main()

一维解法(空间优化)#

import sys
input = sys.stdin.read
def main():
data = input().strip().split()
index = 0
m = int(data[index]) # 物品数量
index += 1
n = int(data[index]) # 背包容量
index += 1
weight = []
for i in range(m):
weight.append(int(data[index]))
index += 1
value = []
for i in range(m):
value.append(int(data[index]))
index += 1
# 一维数组优化:dp[j] 表示容量为 j 时的最大价值
dp = [0] * (n + 1)
for i in range(m):
# 从后往前遍历,避免覆盖之前的状态
for j in range(n, weight[i] - 1, -1):
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
print(dp[n])
main()

416. 分割等和子集#

LeetCode 416. Partition Equal Subset Sum

  • 其实就是个 0-1 背包问题,目标和为 sum(nums) // 2
  • 每个元素只能选择一次,问是否能正好凑出目标和。
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 # 容量为 0 一定能构造
for i in range(n):
# 从后往前遍历,避免覆盖状态
for j in range(target, nums[i] - 1, -1):
dp[j] = dp[j] or dp[j - nums[i]]
return dp[target]
代码随想录算法训练营第三十天 | 动态规划 Part03
https://fuwari.vercel.app/posts/code_musings_day_thirty/
作者
Jarrett
发布于
2025-07-15
许可协议
CC BY-NC-SA 4.0