26春 日总结24

01背包问题

  1. 问题定义
    · 有 n 个物品,每个物品 i 有一个重量 w[i] 和价值 v[i]
    · 给定一个容量为 C 的背包
    · 每个物品只能选一次(0 或 1),目标是让背包内物品总价值最大

  2. 动态规划状态定义
    二维 DP:
    dp[i][j] 表示考虑前 i 个物品,背包容量为 j 时能获得的最大价值。
    转移方程:
    dp[i][j] = max( dp[i-1][j] , dp[i-1][j - w[i]] + v[i] )
    · 不选第 i 个物品 → dp[i-1][j]
    · 选第 i 个物品(前提 j ≥ w[i]) → dp[i-1][j-w[i]] + v[i]
    边界:dp[0][j] = 0(0 个物品时价值为 0)
    最终答案:dp[n][C]

  3. 空间优化(一维滚动数组)
    观察发现 dp[i][j] 只依赖于 i-1 行的数据,因此可以降为一维数组 dp[j]。
    关键:内层循环必须倒序遍历容量,避免同物品被重复使用。

def knapsack_01(weights, values, C):
n = len(weights)
dp = [0] * (C + 1)
for i in range(n):
# 倒序保证每个物品只选一次
for j in range(C, weights[i] - 1, -1):
dp[j] = max(dp[j], dp[j - weights[i]] + values[i])
return dp[C]

  1. 例子
    · n = 3, C = 5
    · 物品1:(w=2, v=4)
    · 物品2:(w=3, v=5)
    · 物品3:(w=4, v=6)
    二维 DP 计算后最优解为:选物品1+物品2,总重5,总价值9。

  2. 复杂度
    · 时间:O(n * C)
    · 空间:O(C)(优化后)

  3. 如何回溯找出选了哪些物品?
    可以用二维 dp 记录选择路径,或额外记录一个 choice[i][j] 数组。常见做法:从 dp[n][C] 倒推,如果 dp[i][j] == dp[i-1][j] 说明没选 i,否则选了 i 并令 j -= w[i]。

posted @ 2026-05-25 22:57  一如初见233  阅读(33)  评论(0)    收藏  举报