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 }
越努力,越幸运