Description
有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份,使得两份的总价值相等
Input
多组输入,每组用例占一行包括六个整数表示这六种物品的数量,以0 0 0 0 0 0结束输入
Output
对于每组用例,输出是否能将这些物品分为价值相同的两份
Sample Input
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
Sample Output
Collection #1:
Can’t be divided.
Collection #2:
Can be divided.
Solution
统计总价值sum,问题转化为背包容量为sum/2的完全背包问题,套模版即可
Code
#include<stdio.h>
#include<string.h>
#define max(x,y) ((x)>(y)?(x):(y))
int dp[111111],num[7],v,flag;
void Complete_Pack(int cost,int weight)
{
for(int i=cost;i<=v;i++)
{
dp[i]=max(dp[i],dp[i-cost]+weight);
if(dp[i]==v)//剪枝
{
flag=1;
return ;
}
}
return ;
}
void ZeroOne_Pack(int cost,int weight)
{
for(int i=v;i>=cost;i--)
{
dp[i]=max(dp[i],dp[i-cost]+weight);
if(dp[i]==v)//剪枝
{
flag=1;
return ;
}
}
return ;
}
void Multiple_Pack(int cost,int weight,int amount)
{
if(cost*amount>=v)
{
Complete_Pack(cost,weight);
return;
}
if(flag) return ;//剪枝
int k=1;
while(k<amount)
{
ZeroOne_Pack(k*cost,k*weight);
if(flag) return ;//剪枝
amount-=k;
k*=2;
}
ZeroOne_Pack(amount*cost,amount*weight);
return ;
}
int main()
{
int res=1;
while(scanf("%d%d%d%d%d%d",&num[1],&num[2],&num[3],&num[4],&num[5],&num[6]))
{
int sum=0;
for(int i=1;i<=6;i++)
sum+=i*num[i];
if(!sum)break;
memset(dp,-1,sizeof(dp));//初始化
dp[0]=0;
flag=0;
v=sum/2;//背包容量为总价值的一半
if(sum%2==0)
for(int i=1;i<=6;i++)
{
Multiple_Pack(i,i,num[i]);//多重背包
if(flag) break;//剪枝
}
printf("Collection #%d:\n",res++);
if(flag)printf("Can be divided.\n\n");
else printf("Can't be divided.\n\n");
}
return 0;
}