poj1014(背包问题)

这道题个人觉得至少有三种解法,第一种背包,第二种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 }

超时了,不知道母函数可不可以优化……

 

posted on 2012-08-18 17:20  矮人狙击手!  阅读(2728)  评论(0编辑  收藏  举报

导航