Mid-Central European Regional Contest 1999
题目大意:给你价值为1、2、3、4、5、6六种宝石的个数,把它按价值
平均分成两份,不能切割,不能分开。问是否能平分
思路:多重背包问题。先判断下宝石总价值是不是偶数,只有偶数才能平
分。若是偶数在用多重背包左。只要总容量为价值的一半的背包能装满就
能平分。多重背包用了二进制的思想。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[120010],num[7],kase = 1,V,sum;
void ZeroOne(int cost,int weight)
{
for(int i = V; i >= cost; i--)
dp[i] = max(dp[i],dp[i-cost]+weight);
}
void Complete(int cost,int weight)
{
for(int i = cost; i <= V; i++)
dp[i] = max(dp[i],dp[i-cost]+weight);
}
void Multiple(int cost,int weight,int cnt)
{
if(V <= cnt*cost)
{
Complete(cost,weight);
return;
}
else
{
int k = 1;
while(k <= cnt)
{
ZeroOne(k*cost,k*weight);
cnt -= k;
k <<= 1;
}
ZeroOne(cnt*cost,cnt*weight);
}
}
int main()
{
while(~scanf("%d%d%d%d%d%d",&num[1],&num[2],&num[3],&num[4],&num[5],&num[6]))
{
sum = num[1]*1 + num[2]*2 + num[3]*3 + num[4]*4 + num[5]*5 + num[6]*6;
if(sum == 0)
break;
printf("Collection #%d:\n",kase++);
if(sum&1)
{
printf("Can't be divided.\n\n");
}
else
{
sum >>= 1;
V = sum;
for(int i = 0; i <= V; i++)
dp[i] = 0;
for(int i = 1; i <= 6; i++)
Multiple(i,i,num[i]);
if(dp[V] == V)
printf("Can be divided.\n\n");
else
printf("Can't be divided.\n\n");
}
}
return 0;
}
原文:http://blog.csdn.net/lianai911/article/details/41574645