Description
每次给你6种商品的数量,第1种商品的价值为1,第2种商品价值为2……第6种商品价值为6。
问能否将商品分成两堆,使得既不拆分商品,且两堆的价值和相等。
Sample Input
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
Sample Output
Collection #1:
Can't be divided.
Collection #2:
Can be divided.
题解:
又是多重背包qwq,刷了一早上水题了。写的时候没有把冒号加上……WA了好几次,感觉自己傻fufu的qwq
既然让分成两堆,还不让拆开,那么首先我们就知道,如果所有商品的价值和为奇数或0,是永远分不出来的。
其次思考如何转化为背包问题:将容量设为总价值和的一半,然后照常做多重背包,如果能刚好拼出来总价值和的一半,就输出Can;如果不能刚好拼出来,那就输出Can‘t
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 using namespace std; 6 const int maxn=100009; 7 int f[maxn],w[maxn],num[maxn],sum[maxn]; 8 int tot=0,all; 9 int main() 10 { 11 while(scanf("%d%d%d%d%d%d",&num[1],&num[2],&num[3],&num[4],&num[5],&num[6])!=EOF) 12 { 13 if(num[1]+num[2]+num[3]+num[4]+num[5]+num[6]==0)break; 14 printf("Collection #%d: ",++tot); 15 for(int i=1;i<=6;i++) 16 w[i]=i; 17 all=0; 18 for(int i=1;i<=6;i++) 19 all+=w[i]*num[i]; 20 int tmp=all; 21 all=tmp/2; 22 memset(f,0,sizeof(f)); 23 for(int i=1;i<=6;i++) 24 { 25 memset(sum,0,sizeof(sum)); 26 for(int j=i;j<=all;j++) 27 { 28 if(f[j]<f[j-w[i]]+w[i]&&sum[j-w[i]]+1<=num[i]) 29 { 30 f[j]=f[j-w[i]]+w[i]; 31 sum[j]=sum[j-w[i]]+1; 32 } 33 } 34 } 35 if(tmp==0)continue; 36 if(tmp%2==1) 37 printf("Can't be divided. "); 38 else 39 { 40 if(f[all]!=all) 41 printf("Can't be divided. "); 42 else 43 printf("Can be divided. "); 44 } 45 } 46 return 0; 47 }