题目链接 Dividing
大意:一系列marbles,是否能平分
看做一个容量为总价值的一半的背包,如果能装满,说明可以平分
第i个物体的的cost和weight都是i
所以最后的判断条件是F[v]==v
剪枝:如果总容量是奇数,一定不能平分
二进制优化见背包九讲
#include <stdio.h>
#include <memory.h>
#include<algorithm>
using namespace std;
int F[120005];
int M[7];
int V;
void ZeroOnePack(int C, int W)
{
for (int v = V; v >= C; v--){
F[v] = max(F[v], F[v - C] + W);
}
}
void CompletePack(int C, int W)
{
for (int v = C; v <= V; v++){
F[v] = max(F[v], F[v - C] + W);
}
}
void MultiplePack(int C, int W, int M)
{
if (C*M >= V){
CompletePack(C, W);
return;
}
int k = 1;
while (k < M){
ZeroOnePack(k*C, k*W);
M = M - k;
k = k * 2;
}
ZeroOnePack(C*M, W*M);
}
int main()
{
//freopen("in.txt", "r", stdin);
int c = 1;
while (1){
memset(F, 0, sizeof(F));
V = 0;
for (int i = 1; i <= 6; ++i){
scanf("%d", &M[i]);
V += M[i] * i;
}
if (!V)break;
printf("Collection #%d:\n", c++);
if (V % 2){
printf("Can't be divided.\n\n");
continue;
}
V = V / 2;
for (int i = 1; i <= 6; ++i)MultiplePack(i, i, M[i]);
if (V == F[V])printf("Can be divided.\n\n");
else printf("Can't be divided.\n\n");
}
return 0;
}