每一个组只能取一个,实际取法就是要么这组一个也不取,要么取第一个要么第二个要么第三个
也就是f[i][j]=max(f[i-1][j],f[i-1][j-v[i][k]+w[i][k],.....,f[i-1][j-v[i][s[i]]+w[i][s[i]]
代码就很简单了
#include<iostream>
using namespace std;
const int N=110;
int w[N][N],v[N][N];//存储第i组的第j个物品的体积和价值
int s[N];//存储每组里面有几个物品
int f[N][N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
for(int j=1;j<=s[i];j++)cin>>v[i][j]>>w[i][j];
}
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
{
f[i][j]=f[i-1][j];//不选第i组里面的任何一个
for(int k=1;k<=s[i];k++)//选出第i组中的一个,并且找到其中的最大
{
if(j>=v[i][k])f[i][j]=max(f[i][j],f[i-1][j-v[i][k]]+w[i][k]);
}
}
cout<<f[n][m]<<endl;
return 0;
}
观察一下代码,我们仍然可以把其优化成一维的
#include<iostream>
using namespace std;
const int N=110;
int w[N][N],v[N][N];//存储第i组的第j个物品的体积和价值
int s[N];//存储每组里面有几个物品
int f[N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
for(int j=1;j<=s[i];j++)cin>>v[i][j]>>w[i][j];
}
for(int i=1;i<=n;i++)
for(int j=m;j>=0;j--)
{
for(int k=1;k<=s[i];k++)//选出第i组中的一个,并且找到其中的最大
{
if(j>=v[i][k])f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
}
}
cout<<f[m]<<endl;
return 0;
}
这里我们就不能像01背包一样写成j=m;j>=v[i],因为不能知道确切的体积