Poj--1014(多重背包)

2014-11-28 01:51:24

思路:多重背包启蒙题,一开始用01背包和dfs乱搞都T了,后来看了多重背包,然后自己YY了下,A掉了。

  把每组物品的n,分解成系数:1,2^1,2^2 ... 2^(k-1) , n - 2^k + 1,我们知道:1+2^1+..+2^(k-1) = 2^k - 1,所以所有系数和为n,又因为数的二进制分解原理,所以1...n中任何一个整数都能表示成几个系数的和。

  预处理下每组物品的系数即可。

 1 /*************************************************************************
 2     > File Name: p1014.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Thu 27 Nov 2014 11:21:14 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 const int maxn = 60000;
27 
28 int num[10];
29 int dp[maxn + 10];
30 int val[10][100],cnt[10];
31 int sum;
32 
33 void Pre(){
34     for(int i = 1; i <= 6; ++i){
35         int n = num[i];
36         cnt[i] = 0;
37         for(int k = 1; k <= n; k <<= 1){
38             val[i][++cnt[i]] = k * i;
39             n -= k;
40         }
41         if(n > 0){
42             val[i][++cnt[i]] = n * i;
43         }
44     }
45 }
46 
47 int main(){
48     int Case = 0;
49     while(~scanf("%d%d%d%d%d%d",num + 1,num + 2,num + 3,num + 4,num + 5,num + 6)){
50         sum = 0;
51         for(int i = 1; i <= 6; ++i){
52             sum += i * num[i];
53         }
54         if(sum == 0)
55             break;
56         printf("Collection #%d:\n",++Case);
57         if(sum % 2){
58             printf("Can't be divided.\n\n");
59             continue;
60         }
61         sum /= 2;
62         Pre();
63         memset(dp,0,sizeof(dp));
64         for(int i = 1; i <= 6; ++i){
65             for(int o = 1; o <= cnt[i] ; ++o){
66                 for(int j = sum; j >= val[i][o]; --j){
67                     dp[j] = max(dp[j],dp[j - val[i][o]] + val[i][o]);
68                 }
69             }
70         }
71         if(dp[sum] == sum)
72             printf("Can be divided.\n\n");
73         else
74             printf("Can't be divided.\n\n");
75     }
76     return 0;
77 }

 

posted @ 2014-11-28 01:54  Naturain  阅读(134)  评论(0编辑  收藏  举报