关键词: 01背包,多重背包的二进制拆分
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#define MAX 300010
using namespace std;
int num[MAX];
int cou,sum;
void add(int k, int value) { //多重背包的二进制拆分
for(int i = 0; ; i++) {
int tmp = 1 << i;
int next = 1 << (i + 1);
if(k - next + 1 <= 0) {
if(k != 0)
num[cou++] = (k - tmp + 1) * value;
return;
}
num[cou++] = value * tmp;
}
}
int flag,bag[MAX];
int DP() { // 01背包
int i,k;
for (int i = 0;i < cou; i ++)
for (int k = sum; k >= num[i]; k --)
if(bag[k - num[i]] + num[i] > bag[k])
bag[k] = bag[k - num[i]] + num[i];
return bag[sum] == sum ;
}
int main() {
int a, b, c,d, e, f;
int cas = 1;
while (scanf ("%d%d%d%d%d%d", &a, &b, &c, &d, &e, &f) != EOF) {
sum = cou = 0;
if(!( a || b || c || d || e || f ))
break;
sum += a * 1;
sum += b * 2;
sum += c * 3;
sum += d * 4;
sum += e * 5;
sum += f * 6;
printf("Collection #%d:\n", cas++);
if(sum % 2 == 1) { // 要是价值总量是奇数的话肯定是不符合的直接判断
printf("Can't be divided.\n\n");
continue;
}
add(a, 1);
add(b, 2);
add(c, 3);
add(d, 4);
add(e, 5);
add(f, 6);
sum /= 2;
memset(bag, 0, sizeof(bag));
flag = DP();
if(flag)
printf("Can be divided.\n\n");
else
printf("Can't be divided.\n\n");
}
return 0;
}