原题链接:
二维:
题解:
相比于之前的01背包问题,完全背包的每种物品都有无限件可用。
分为2种情况:选和不选
不选的情况和之前的相同,都是f[i-1][j]
选的情况中,就需要考虑选当前物品多少个,列出如下公式。
可以发现紫框部分=绿框部分+w,因此进行替换得到:
代码:
#include<bits/stdc++.h>
using namespace std;
int n, V;
const int N = 1e3 + 10;
int v[N], w[N];
int f[N][N];//f[i][j]表示考虑前i个物品,在背包容量为j的前提下的最优解
int main() {
cin >> n >> V;
for (int i = 1;i <= n;i++) cin >> v[i] >> w[i];
for (int i = 1;i <= n;i++) {
for (int j = 0;j <= V;j++) {
f[i][j] = f[i - 1][j];//不选第i个物品
if (v[i] <= j) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);//选择第i个物品
}
}
cout << f[n][V];
}
一维:
题解:
和01背包同理,对二维进行等价化转换为一维。
但是因为更新公式进行了调整,从:
调整为:
因此我们需要将01背包中容量的遍历顺序改为顺序,这是因为f[i][j-v]代表更新的时候要依赖于当前轮的状态。
代码:
#include<bits/stdc++.h>
using namespace std;
int n, V;
const int N = 1e3 + 10;
int v[N], w[N];
int f[N];//f[j]表示在背包容量为j的前提下的最优解
int main() {
cin >> n >> V;
for (int i = 1;i <= n;i++) cin >> v[i] >> w[i];
for (int i = 1;i <= n;i++) {
for (int j = v[i];j <= V;j++) {
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
cout << f[V];
}