hdu-1059 Dividing---多重背包

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1059

题目大意:

就是有价值1、2、3、4、5、6的硬币各多少个,然后让你判断能否把他们分成价值相等的两部分。

思路:

多重背包的模板

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 const int INF = 0x3f3f3f3f;
 6 const int maxn = 200000 + 10;
 7 int n, m, cases;
 8 int dp[maxn];
 9 int sum;
10 
11 void ZeroOnePack(int cost, int value)
12 {
13     for(int v = sum; v >= cost; v--)//01背包正序
14         dp[v] = max(dp[v], dp[v - cost] + value);
15 }
16 
17 void CompletePack(int cost, int value)
18 {
19     for(int v = cost; v <= sum; v++)
20         dp[v] = max(dp[v], dp[v - cost] + value);
21 }
22 void MutiplePack(int cost, int value, int amount)
23 {
24     if(cost * amount >= sum)//超过总体积,进行完全背包
25         CompletePack(cost, value);
26     else
27     {
28         int k = 1;//二进制优化
29         while(k <= amount)
30         {
31             ZeroOnePack(k * cost, k * value);
32             amount -= k;
33             k *= 2;
34         }
35         ZeroOnePack(amount * cost, amount * value);
36     }
37 }
38 int main()
39 {
40     int a[10];
41     while(cin >> a[1] >> a[2] >> a[3] >> a[4] >> a[5] >> a[6])
42     {
43         //if(a[1] + a[2] + a[3] + a[4] + a[5] + a[6] == 0)break;
44         if(!a[1]&&!a[2]&&!a[3]&&!a[4]&&!a[5]&&!a[6])break;
45         sum = 0;
46         for(int i = 1; i <= 6; i++)sum += i * a[i];
47         printf("Collection #%d:\n",++cases);
48         if(sum & 1)//总和为奇数,一定不能均分
49         {
50             printf("Can't be divided.\n\n");
51             continue;
52         }
53         memset(dp, 0, sizeof(dp));
54         sum /= 2;
55         for(int i = 1; i <= 6; i++)
56             MutiplePack(i, i, a[i]);//多重背包
57         if(dp[sum] == sum)
58             printf("Can be divided.\n\n");
59         else printf("Can't be divided.\n\n");
60     }
61     return 0;
62 }

 

posted @ 2018-04-14 14:02  _努力努力再努力x  阅读(131)  评论(0编辑  收藏  举报