🎒 背包问题的四大经典类型
类型 | 物品数量 | 每个物品能否重复选 | 对应问题 | 循环顺序 |
---|
0-1 背包 | 有限 | 每个物品只能选一次 | 选或不选 | 容量在内层(倒序) |
完全背包 | 无限 | 每个物品可重复选 | 组合数、零钱兑换 | 容量在内层(顺序),物品在外层 |
多重背包 | 有限 | 每个物品最多选 k 次 | 扩展型 | 可以转换为多个 0-1 背包 |
分组背包 | 分组有限 | 每组最多选一个物品 | 分组选择 | 每组内物品做 0-1 背包 |
💡 简析每种类型
1. 0-1 背包问题
- 每个物品最多只能选一次
- 物品在外层,容量倒序遍历(避免重复选择)
- 常用于:最大价值问题,选择是否放入物品
- 示例代码结构:
for (int i = 0; i < n; i++) {
for (int j = capacity; j >= weight[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
2. 完全背包问题
- 每种物品可以无限次使用
- 物品在外层,容量正序遍历(允许重复使用)
- 常用于:硬币兑换问题(Leetcode 518 零钱兑换 II)
- 示例结构:
for (int i = 0; i < n; i++) {
for (int j = weight[i]; j <= capacity; j++) {
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
3. 多重背包问题
- 每种物品最多用
k
次 - 解决方法:
- 转换为多个 0-1 背包(例如 3 件 A → 拆成 3 个 A)
- 更优做法:二进制优化(拆分为
1, 2, 4...
等次方组合)
4. 分组背包问题
- 多个物品分组,每组最多只能选一个
- 每组内部做一次 0-1 背包选择
- 用于:角色装备选择、选修课、产品组合
🎯 背包问题的循环结构总结
背包类型 | 外层循环 | 内层循环 | 备注 |
---|
0-1 背包 | 遍历物品 | 容量 倒序 | 防止重复选择 |
完全背包 | 遍历物品 | 容量 正序 | 允许重复选择 |
多重背包 | 拆成多个 0-1 背包 | 同 0-1 背包 | 或用二进制优化 |
分组背包 | 遍历分组 | 遍历每组内物品 + 容量倒序 | 每组最多选一个 |