多重背包:每个物品有多个
任意数多能用2的倍数相加表示(2进制优化)
多重背包可转化为 0-1 背包
多组测试样例记得重置 f 数组
memset ( f , 0 , sizeof (f) )
#include <bits/stdc++.h>
using namespace std;
const int N=20100,M=2010;
int v[N],w[N];//合并之后每个物品的体积和价值
int f[M];//存储答案
int main(){
int t;
cin>>t;
while(t--){
memset(f,0,sizeof(f));
int n,m;//n个物品,背包体积为m
cin>>m>>n;
int cnt=0;//合并之后新物品的下标
while(n--){//合并物品
int a,b,s;//每个物品的体积,价值,数量
cin>>a>>b>>s;
int k=1;//k每次增长2的倍数
while(k<=s){
cnt++;//先cnt++,下标从1开始
v[cnt]=a*k;
w[cnt]=b*k;
s-=k;//合并之后物品数量减少
k*=2;//k倍增
}
if(s>0){//物品还有剩余
cnt++;
v[cnt]=a*s;
w[cnt]=b*s;
}
} //合并完成
n=cnt;//更新合并之后的物品数量
for(int i=1;i<=n;i++)//0-1背包
for(int j=m;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);
cout<<f[m]<<endl;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N=20100,M=2010;
int v[N],w[N];//合并之后每个物品的体积和价值
int f[M];//存储答案
int main(){
int n,m;//n个物品,背包体积为m
cin>>n>>m;
int cnt=0;//合并之后新物品的下标
while(n--){//合并物品
int a,b,s;//每个物品的体积,价值,数量
cin>>a>>b>>s;
int k=1;//k每次增长2的倍数
while(k<=s){
cnt++;//先cnt++,下标从1开始
v[cnt]=a*k;
w[cnt]=b*k;
s-=k;//合并之后物品数量减少
k*=2;//k倍增
}
if(s>0){//物品还有剩余
cnt++;
v[cnt]=a*s;
w[cnt]=b*s;
}
} //合并完成
n=cnt;//更新合并之后的物品数量
for(int i=1;i<=n;i++)//0-1背包
for(int j=m;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);
cout<<f[m]<<endl;
return 0;
}