朴素做法:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e3 + 10;
int f[N][N];
int v[N], w[N];
int n, m;
int main()
{
cin >> n >> m;
for (int i=1; i <= n; i ++)
cin >> v[i] >> w[i];
核心思想:从前i种物品里面选,每种物品的数量无限,所以只要所选物品的总体积不超过背包体积,你就可以无限选!
而相比于01背包,这里枚举的是每种物品选多少件凑在一起才会使得价值最大。
比如:两种物品,第一种物品选10件好,还是选100件好,好不好取决于两种物品的总价值能否更大,
所以枚举第一种物品选不同件数下,第二种物品所能选的最大价值。
而01背包的话:则是第i件物品选还是不选好,好取决于选了它后总价值是否会更大!
for (int i=1; i <= n; i ++) //从前i种物品里面选!
{
for (int j=1; j <= m; j ++)
{
for (int k=0; k*v[i] <= j; k ++)
{
f[i][j] = max(f[i][j], f[i-1][j-k*v[i]] + k*w[i]); //表示第i种物品不选的价值和选第i种物品选k件的价值!
}
}
}
cout << f[n][m] << endl;
return 0;
}
滚动数组优化:
#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int f[N];
int n, m;
int main()
{
cin >> n >> m;
for (int i=1; i <= n; i ++)
{
int v, w;
cin >> v >> w;
for (int j=v; j <= m; j ++) //用新值更新新值,即第i件物品选了后的价值,我还选第i件物品,在第i件物品的基础上更新下一次选第i件物品的价值
f[j] = max(f[j], f[j-v] + w);
}
cout << f[m] << endl;
return 0;
}