1. 动态规划思路
完全背包问题和 0-1 背包问题非常相似,区别仅在于不限制物品的选择次数。
- 在 0-1 背包问题中,每种物品只有一个,因此将物品 i 放入背包后,只i能从前 i−1 个物品中选择。
- 在完全背包问题中,每种物品的数量是无限的,因此将物品 i 放入背包后,仍可以从前 i 个物品中选择。
在完全背包问题的规定下,状态 [i,c] 的变化分为两种情况。
- 不放入物品 � :与 0-1 背包问题相同,转移至 [i−1,c] 。
- 放入物品 � :与 0-1 背包问题不同,转移至 [i,c−wgt[i−1]] 。
从而状态转移方程变为:
dp[i][c] = myMax(dp[i - 1][c], dp[i][c - wgt[i - 1]] + val[i - 1])
核心代码:
for (int i = 1; i <= n; i++) {for (int c = 1; c <= cap; c++) {if (wgt[i - 1] > c) {// 若超过背包容量,则不选物品 idp[i][c] = dp[i - 1][c];} else {// 不选和选物品 i 这两种方案的较大值dp[i][c] = myMax(dp[i - 1][c], dp[i][c - wgt[i - 1]] + val[i - 1]);}}}int res = dp[n][cap];// 释放内存
3. 空间优化
由于当前状态是从左边和上边的状态转移而来的,因此空间优化后应该对 dp 表中的每一行进行正序遍历。
这个遍历顺序与 0-1 背包正好相反。
for (int i = 1; i <= n; i++) {for (int c = 1; c <= cap; c++) {if (wgt[i - 1] > c) {// 若超过背包容量,则不选物品 idp[c] = dp[c];} else {// 不选和选物品 i 这两种方案的较大值dp[c] = myMax(dp[c], dp[c - wgt[i - 1]] + val[i - 1]);}}}