1 /*问你能不能将给出的资源平分成两半,那么我们就以一半为背包,运行多重背包模版 2 但是注意了,由于个数过大,直接运行会超时,所以要用二进制拆分每种的个数*/ 3 #include<stdio.h> 4 #include<string.h> 5 #include<algorithm> 6 using namespace std; 7 int w[120005],vr[120005],dp[120005]; 8 int a[7],v[7]; 9 int numw; 10 void cf(int n,int ok) 11 { 12 int i,j,sum,e; 13 e=sum=1; 14 while(sum<=n) 15 { 16 vr[numw]=v[ok]; 17 w[numw++]=e; 18 e*=2; 19 sum+=e; 20 } 21 if(n-(sum-e)>0) 22 { 23 w[numw]=n-(sum-e); 24 vr[numw]=v[ok]; 25 numw++; 26 } 27 } 28 int main() 29 { 30 int i,j,n,m,k; 31 int n1,n2,n3,n4,n5,n6; 32 int cas=0; 33 while(scanf("%d%d%d%d%d%d",&n1,&n2,&n3,&n4,&n5,&n6)!=EOF) 34 { 35 if(n1==0 && n2==0 && n3==0 && n4==0 && n5==0 && n6==0) break; 36 int num=1; 37 if(n1!=0) { a[num]=n1; v[num++]=1;} 38 if(n2!=0) { a[num]=n2; v[num++]=2;} 39 if(n3!=0) { a[num]=n3; v[num++]=3;} 40 if(n4!=0) { a[num]=n4; v[num++]=4;} 41 if(n5!=0) { a[num]=n5; v[num++]=5;} 42 if(n6!=0) { a[num]=n6; v[num++]=6;} 43 int sum=0; 44 //printf("%d ",num); 45 for(i=1;i<num;i++) 46 { 47 sum=sum+a[i]*v[i]; 48 } 49 if(sum==0) break; 50 if(sum%2) 51 { 52 printf("Collection #%d: ",++cas); 53 printf("Can't be divided. "); 54 continue; 55 } 56 numw=1; 57 for(i=0;i<=sum/2;i++) 58 dp[i]=0; 59 for(i=1;i<num;i++) 60 { 61 cf(a[i],i); 62 } 63 for(i=1;i<numw;i++) 64 for(j=sum/2;j>=w[i]*vr[i];j--) 65 dp[j]=max(dp[j],dp[j-w[i]*vr[i]]+w[i]*vr[i]); 66 printf("Collection #%d: ",++cas); 67 if(dp[sum/2]==sum-dp[sum/2]) printf("Can be divided. "); 68 else printf("Can't be divided. "); 69 } 70 return 0; 71 }