背包 DP
概念讲解
背包问题分类
| 类型 | 特点 |
|---|---|
| 0-1 背包 | 每个物品只能选一次 |
| 完全背包 | 每个物品可以选无限次 |
| 多重背包 | 每个物品有数量限制 |
| 分组背包 | 物品分组,每组选一个 |
0-1 背包
问题
n 个物品,容量 W,每个物品有重量 w[i] 和价值 v[i],求最大价值。
代码
123456int dp[W+1];
for (int i = 0; i < n; i++) {
for (int j = W; j >= w[i]; j--) { // 逆序
dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
}
}时间复杂度:
完全背包
123456int dp[W+1];
for (int i = 0; i < n; i++) {
for (int j = w[i]; j <= W; j++) { // 正序
dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
}
}多重背包
12345678int dp[W+1];
for (int i = 0; i < n; i++) {
for (int j = W; j >= w[i]; j--) {
for (int k = 1; k <= s[i] && k*w[i] <= j; k++) {
dp[j] = max(dp[j], dp[j-k*w[i]] + k*v[i]);
}
}
}考点分析
初赛考查方式
- 程序阅读: 背包程序
- 编程题: 背包应用
常见考点
- 0-1 背包
- 完全背包
- 遍历顺序
例题精讲
例题 1:0-1 背包
题目: 3 个物品,容量 5,重量 {2,3,4},价值 {3,4,5}。
解答:
选物品 1 和 2,重量 5,价值 7。
练习题
- 0-1 背包和完全背包的区别是什么?
查看答案
| 特性 | 0-1 背包 | 完全背包 |
|---|---|---|
| 物品选择 | 每个物品只能选一次 | 每个物品可以选无限次 |
| 遍历顺序 | 逆序 | 正序 |
| 状态转移 | dp[j] = max(dp[j], dp[j-w] + v) |
dp[j] = max(dp[j], dp[j-w] + v) |
- 为什么 0-1 背包要逆序遍历?
查看答案
逆序遍历保证每个物品只被选一次。
如果正序遍历:
dp[j-w]可能已经包含了当前物品- 会导致同一个物品被选多次
- 多重背包的时间复杂度是多少?
查看答案
- n 是物品数量
- W 是背包容量
- s 是每个物品的最大数量
可以二进制优化到
易错点
⚠️ 注意:
- 0-1 背包逆序,完全背包正序
- 注意初始化
- 多重背包可以二进制优化
- 分组背包要注意遍历顺序