一、题目描述
当前有 N 种物品,第 i 种物品的体积是 ci,价值是 wi。 每种物品的数量都是无限的,可以任意选择若干件。 现有容量为 V 的背包,请你放入若干物品,使总体积不超过 V,并且总价值尽可能大。 这就是完全背包问题,和 01 背包的区别就是物品无限多个。
二、解法
虽然物品个数是无限的,但是实际上,由于背包容量有上限,每个物品最多选取的个数也是有限制的,这样可以转换成多重背包问题,进而可以转换成 01 背包问题。 可以用多重背包的思想来解决完全背包。
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
for (int k = 0; k * c[i] <= j; k++) {
dp[i][j] = max(dp[i - 1][j - c[i] * k] + w[i] * k, dp[i][j]);
}
}
}
时间优化:
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= v; j++) {
if (j >= c[i]) {
dp[i][j] = max(dp[i][j - c[i]] + w[i], dp[i - 1][j]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
这样我们的的算法时间复杂度 O(NV),空间复杂度 O(NV)
不难发现,我们也可以把空间复杂度优化下来,优化成 O(V)。
for (int i = 1; i <= n; i++) {
for (int j = c[i]; j <= v; j++) {
dp[j] = max(dp[j - c[i]] + w[i], dp[j]);
}
}
与 01 背包相比,完全背包只是第二重循环的顺序发生了翻转。