DP大作战—组合背包
题目描述
组合背包:有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。
DD大牛的伪代码
for i = 1 to N
if 第i件物品属于01背包
ZeroOnePack(F,Ci,Wi)
else if 第i件物品属于完全背包
CompletePack(F,Ci,Wi)
else if 第i件物品属于多重背包
MultiplePack(F,Ci,Wi,Ni)
输入
第一个数为数据组数n 1<=n<=10
接下来n组测试数据,每组测试数据由2部分组成。
第一行为背包容量V,物品种类数N。1<=V<=30000,1<=N<=200
接下来N行每行三个数为物品价值v,物品重量w,物品件数M。M=233表示物品无限。
1<=v,w<=200, 1<=M<=25
输出
对于每组数据,输出一行,背包能容纳的最大物品价值
输入样例
1
10 3
2 2 233
3 2 1
4 3 3
输出样例
13
题目来源:http://biancheng.love/contest/10/problem/F/index
解题思路:
组合背包:0-1背包、完全背包、多重背包。
因此需要结合上述三种背包问题的解决方法来solve组合背包
0-1背包代码:
1 void Zeronepack(int w,int v) 2 { 3 for(int i=V; i>=w; i--) 4 if(dp[i]<dp[i-w]+v) 5 dp[i]=dp[i-w]+v; 6 }
完全背包代码:
1 void Compack(int w,int v) 2 { 3 for(int i=w; i<=V; i++) 4 if(dp[i]<dp[i-w]+v) 5 dp[i]=dp[i-w]+v; 6 }
多重背包代码:
1 void Multipack(int w,int v,int num) 2 { 3 int k; 4 if(w*num>=V) 5 { 6 Compack(w,v); 7 return; 8 } 9 for(k=1; k<num; k<<1) 10 { 11 Zeronepack(k*w,k*v); 12 num-=k; 13 } 14 Zeronepack(num*w,num*v); 15 }
本题组合背包代码:
1 #include <bits/stdc++.h> 2 int dp[30005]; 3 int V,N; 4 5 void Compack(int w,int v) 6 { 7 for(int i=w; i<=V; i++) 8 if(dp[i]<dp[i-w]+v) 9 dp[i]=dp[i-w]+v; 10 } 11 12 void Zeronepack(int w,int v) 13 { 14 for(int i=V; i>=w; i--) 15 if(dp[i]<dp[i-w]+v) 16 dp[i]=dp[i-w]+v; 17 } 18 19 void Multipack(int w,int v,int num) 20 { 21 int k; 22 if(w*num>=V) 23 { 24 Compack(w,v); 25 return; 26 } 27 for(k=1; k<num; k<<1) 28 { 29 Zeronepack(k*w,k*v); 30 num-=k; 31 } 32 Zeronepack(num*w,num*v); 33 } 34 35 int main() 36 { 37 int kase,v,w,m; 38 scanf("%d",&kase); 39 while(kase--) 40 { 41 memset(dp,0,sizeof(dp)); 42 scanf("%d%d",&V,&N); 43 for(int i=1;i<=N;i++) 44 { 45 scanf("%d%d%d",&v,&w,&m); 46 if(m==1) 47 Zeronepack(w,v); 48 else if(m==233) 49 Compack(w,v); 50 else 51 Multipack(w,v,m); 52 } 53 printf("%d\n",dp[V]); 54 } 55 return 0; 56 }
作者: 伊甸一点
出处: http://www.cnblogs.com/zpfbuaa/
本文版权归作者伊甸一点所有,欢迎转载和商用(须保留此段声明),且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文链接 如有问题, 可邮件(zpflyfe@163.com)咨询.