組合背包:有的物品只可以取一次(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 }