这道题个人觉得至少有三种解法,第一种背包,第二种dfs,第三种母函数
这道题我用的是背包问题来求的,首先这个问题是多重背包问题,看了背包九讲,多重背包可以转化为01背包,这道题继续把他转化了,因为如果数据过大,效率就得不到保证,为了提高效率,采用了二进制拆分的方法,
关于二进制拆分的方法简答来说是这样的:
假设原来某一种类的珠宝数量为N,我们可以把N拆成1,2,4,8,……,2^(k-1),N-2^k+1。这些拆分成的数字能够表示1~N之间的任何一个数。
这样,我们就把物品数减小为logN(以2为底,向上取整)。
这样把原来的物体转化为了一个一个的单位,以单位计算,这样就成功的把多重背包问题转化为了纯粹的01背包问题
1 #include<stdio.h> 2 #include <cstring> 3 using namespace std; 4 int a[10]; 5 int sum=0; 6 int dp[60050]; 7 8 int max(int a ,int b) 9 { 10 return a>b?a:b; 11 } 12 13 struct node 14 { 15 int value; 16 int amount; 17 }; 18 node divide[100]; 19 int c=1; 20 int main() 21 { 22 while(1) 23 { 24 sum=0; 25 memset(dp,0,sizeof(dp)); 26 for(int i=1;i<=6;i++) 27 { 28 scanf("%d",&a[i]); 29 sum+=a[i]*i; 30 } 31 if(sum==0) break; 32 int count=0; 33 for(int i=1;i<=6;i++)//二进制分割 34 { 35 int k=1; 36 int m=a[i]; 37 while(k<=m) 38 { 39 divide[count].value=i; 40 divide[count++].amount=k; 41 m=m-k; 42 k=k*2; 43 } 44 divide[count].value=i; 45 divide[count++].amount=m; 46 } 47 printf("Collection #%d:\n",c++); 48 if((sum%2)!=0) 49 { 50 printf("Can't be divided.\n"); 51 printf("\n"); 52 continue; 53 } 54 else sum=sum/2; 55 for(int i=0;i<count;i++) 56 { 57 int tmp=divide[i].amount*divide[i].value; 58 for(int j=sum;j>=tmp;j--) 59 { 60 dp[j]=max(dp[j],dp[j-tmp]+tmp); 61 } 62 } 63 64 if(dp[sum]==sum) 65 { 66 printf("Can be divided.\n"); 67 printf("\n"); 68 } 69 else 70 { 71 printf("Can't be divided.\n"); 72 printf("\n"); 73 } 74 } 75 return 0; 76 }
dfs我是不太会,母函数的话 ,我先试下,以后再续……
母函数的方法,看了三重循环就感觉要超时,果然啊
1 #include <stdio.h> 2 #include <cstring> 3 int a[10]; 4 int sum; 5 int b[60050]; 6 int tmp[60050]; 7 int main() 8 { 9 int k=1; 10 while(1) 11 { 12 memset(tmp,0,sizeof(tmp)); 13 memset(b,0,sizeof(b)); 14 sum=0; 15 for(int i=1;i<=6;i++) 16 { 17 scanf("%d",&a[i]); 18 sum+=a[i]*i; 19 } 20 if(sum==0) break; 21 printf("Collection #%d\n",k++); 22 if((sum%2)!=0) 23 { 24 printf("Can't be divided.\n"); 25 printf("\n"); 26 continue; 27 } 28 else 29 { 30 sum=sum/2; 31 for(int i=0;i<=a[1];i++) 32 { 33 b[i]=1; 34 } 35 for(int i=2;i<=6;i++) 36 { 37 for(int j=0;j<=sum;j++) 38 { 39 for(int m=0;m*i+j<=sum && m<=a[i];m++) 40 tmp[m*i+j]+=b[j]; 41 } 42 for(int j=0;j<=sum;j++) 43 { 44 b[j]=tmp[j]; 45 tmp[j]=0; 46 } 47 } 48 if(b[sum]!=0) 49 { 50 printf("Can be divided.\n"); 51 printf("\n"); 52 continue; 53 } 54 else 55 { 56 printf("Can't be divided.\n"); 57 printf("\n"); 58 continue; 59 } 60 } 61 } 62 return 0; 63 }
超时了,不知道母函数可不可以优化……