POJ 1014 Dividing【多重背包+二进制优化】
大意:
价值1, 2, 3, ……, 6的物品分别a1, a2, ……, a5, a6件
问能否把这些物品分成两份,使其具有相同的价值(所有物品必须全部用上)
分析:
给个物品有多件,即多重背包
只要看能不能将这些物品拼成 总价值 的 一半就可以了
转化为01背包是用二进制优化,否则会超时
代码:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int maxn = 20005 * 6; 7 8 int n, all; 9 int vo[maxn]; 10 int dp[maxn]; 11 bool solve() { 12 if(all % 2 == 1) return false; 13 all /= 2; 14 memset(dp, 0, sizeof(dp)); 15 for(int i = 1; i <= n; i++) { 16 if(vo[i] > all) return false; 17 for(int j = all; j >= vo[i]; j--) { 18 dp[j] = max(dp[j], dp[j - vo[i]] + vo[i]); 19 } 20 } 21 if(dp[all] != all) return false; 22 return true; 23 } 24 25 int main() { 26 int a[10]; 27 int kase = 1; 28 while(scanf("%d %d %d %d %d %d",&a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) ) { 29 all = 0; 30 for(int i = 1; i <= 6; i++) { 31 all += a[i] * i; 32 } 33 if(all == 0) break; 34 n = 1; 35 for(int i = 1; i <= 6; i++) { 36 for(int k = 1; k <= a[i]; k *= 2) { 37 vo[n++] = k * i; 38 a[i] -= k; 39 } 40 if(a[i]) vo[n++] = a[i] * i; 41 } 42 n--; 43 printf("Collection #%d:\n", kase++); 44 puts(solve() ? "Can be divided." : "Can't be divided."); 45 puts(""); 46 } 47 return 0; 48 }