poj 1014 - 多重背包

关键词:  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;
}


你可能感兴趣的:(poj 1014 - 多重背包)