对于一个多重背包问题,思路有两种:
1.转化为01背包(只需要按照每个物品的个数展开即可);
2.再嵌套一层循环来便利物品数量;
对于1,代码如下:
const int N=1e4+10;
int vol[N],weal[N];
int dp[N];
int main()
{
int n,v;
cin>>n>>v;
int size=0;
for(int i=0;i<n;i++)
{
int vi,wi,si;
cin>>vi>>wi>>si;
while(si--)
{
vol[size]=vi;
weal[size]=wi;
size++;
}
}
for(int i=0;i<size;i++)
{
for(int j=v;j>=vol[i];j--)
{
dp[j]=max(dp[j],dp[j-vol[i]]+weal[i]);
}
}
cout<<dp[v]<<endl;
return 0;
}
但是在遇到一些物品数量取值非常大的时候我们就会发现会超时,因为时间复杂度实际上是
O(n3),但是我们还是可以利用拆分的思想把问题转化为01背包。我们不拆成1 1 1 1....的形式而是1 2 4 5 8 ......n的形式,n的取值取决于物品个数拆分后剩下的不为2的n次方的余数。这样就把n的拆分简化了log2 n;
代码如下
int main()
{
int n,v;
cin>>n>>v;
int size=0;
for(int i=0;i<n;i++)
{
int vi,wi,si;
cin>>vi>>wi>>si;
while(si--)
{
vol[size]=vi;
weal[size]=wi;
size++;
}
}
for(int i=0;i<size;i++)
{
for(int j=v;j>=vol[i];j--)
{
dp[j]=max(dp[j],dp[j-vol[i]]+weal[i]);
}
}
cout<<dp[v]<<endl;
return 0;
}