我们首先来介绍一下多重背包是什么
可以这样理解:01背包≤多重背包≤完全背包
01背包每种物品最多选一件
完全背包每种物品可以选无数件,但受限制于背包的容量
多重背包每种物品可以选的件数是给出的,同样也受限制于背包的容量
多重背包在实现的时候可以进行二进制优化,大致思路是放多件的情况可以进行拆分成几种放少件的情况,之前放少件的情况已经考虑过了,放多件的情况就不用考虑这些拆出来的情况了
接下来我们引出混合三种背包的问题
每种物品可以放1件,可以放无限件,也可以放若干件,问背包所能放物品的最大的价值
我们给出01和完全背包的实现:
int f[maxv]; void zpack(int v0,int w0) { for(int i=V;i>=v0;i--) f[i]=max(f[i],f[i-v0]+w0); } void cpack(int v0,int w0) { for(int i=v0;i<=V;i++) f[i]=max(f[i],f[i-v0]+w0); }
接下来考虑多重背包的情况,用2进制方法拆成01去处理,拆不出来的再放一次
for(int j=1;j<=m[i];j*=2) { zpack(v[i]*j,w[i]*j); m[i]-=j; } zpack(m[i]*v[i],m[i]*w[i]);
这样我们的问题解决了,下面给出完整的实现,物品数无限本题是用-1来表示的
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int maxv=200005,maxn=205; 5 int N,V; 6 int v[maxn],w[maxn],m[maxn]; 7 long long ans=0; 8 // 9 int f[maxv]; 10 void zpack(int v0,int w0) 11 { 12 for(int i=V;i>=v0;i--) 13 f[i]=max(f[i],f[i-v0]+w0); 14 } 15 void cpack(int v0,int w0) 16 { 17 for(int i=v0;i<=V;i++) 18 f[i]=max(f[i],f[i-v0]+w0); 19 } 20 int main() 21 { 22 cin>>N>>V; 23 for(int i=1;i<=N;i++) 24 cin>>v[i]>>w[i]>>m[i]; 25 for(int i=1;i<=N;i++) 26 { 27 if(m[i]==-1||m[i]*v[i]>V) 28 cpack(v[i],w[i]); 29 else 30 { 31 for(int j=1;j<=m[i];j*=2) 32 { 33 zpack(v[i]*j,w[i]*j); 34 m[i]-=j; 35 } 36 zpack(m[i]*v[i],m[i]*w[i]); 37 } 38 } 39 ans=f[V]; 40 cout<<ans<<endl; 41 return 0; 42 }