0-1 背包与动态规划入门
Views: --
有 件物品,第 件重量 、价值 ,背包容量为 。每件物品只能完整地选一次或不选,求最大总价值。
1. 为什么暴力是指数级
每件物品有“选/不选”两种决策,共有 个子集。逐个检查得到 算法。
递归写成:
朴素递归会反复计算相同的 ,这正是动态规划要消除的重叠子问题。
2. 状态定义
令
表示只考虑前 件物品、容量不超过 时的最大价值。
状态必须包含“已经处理到哪件物品”,否则无法保证每件只使用一次。
3. 状态转移
对第 件物品:
- 不选:价值是 ;
- 选:需要 ,价值是 。
因此
边界为 ,答案是 。
4. 为什么转移正确
任意最优方案对第 件物品只有两种情况:
- 不含它,则剩余方案一定是前 件、容量 下的最优解;
- 含它,去掉它后一定是前 件、容量 下的最优解。
若剩余部分不是最优,就能替换成更优子方案并改进原方案,矛盾。这就是最优子结构。
5. 复杂度与伪多项式
状态数为 ,每个状态 转移:
这不是关于输入位数的真正多项式时间。容量 用二进制表示只需 位,而算法依赖数值 ,所以称为伪多项式算法。
6. 一维空间压缩
第 行只依赖第 行,可压缩为:
dp[0..W] = 0
for each item i:
for c = W down to w[i]:
dp[c] = max(dp[c], dp[c - w[i]] + v[i])
容量必须从大到小枚举。若从小到大,刚更新的 会被当前物品再次使用,算法就变成完全背包。
空间降为 。
7. 一个例子
容量 ,物品为
最优方案选择重量 3 和 4 的物品,总重量 7、总价值 9。虽然重量 5 的物品单件价值最高,但选它后剩余容量无法组成更优方案,这说明局部贪心不可靠。
8. 恢复选择方案
保留二维表时,从 反向判断:
- 若 ,第 件可不选;
- 否则选了第 件,记录它并令 。
若存在相等的两种最优转移,方案可能不唯一。需要字典序或物品数等次级目标时,要把规则写进状态或回溯策略。
9. 常见变体
- 完全背包:每件可无限次,容量从小到大枚举;
- 多重背包:每件有数量上限,可二进制拆分;
- 恰好装满:除 外初始化为 ;
- 价值维 DP:当价值和较小而容量很大时,求达到某价值的最小重量;
- 二维费用:状态加入第二个容量维度。
10. 0-1 与分数背包的分界
分数背包允许切分物品,按单位重量价值贪心正确;0-1 背包不允许切分,容量离散效应会破坏交换论证,因此需要动态规划或其他组合优化方法。