【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=1059
题目意思
题目大意:给你价值为1到6的物品各ai个,问这写物品的价值是否可以平分
解题思路
给的数据时间非常微妙,如果直接01背包跑会哇,但是用多重背包不跑完全背包部分又可以过,所以直接把各物品数量按二进制来分解,然后跑01就可以了(如13分为:1 2 4 6,这4个数字任意组合可以得到1到13的任意数)
代码部分
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=15;
const int INF=0x3f3f3f;
int dp[60005];
int v1[60005],w1[60005];
int main()
{
int bj=0;
int v[10]={1,2,3,4,5,6};
int ans[10];
while(~scanf("%d %d %d %d %d %d",&ans[0],&ans[1],&ans[2],&ans[3],&ans[4],&ans[5]))
{
if(ans[0]+ans[1]+ans[2]+ans[3]+ans[4]+ans[5]==0)
break;
bj++;
int k=0;
int sum,half;
sum=ans[0]*v[0]+ans[1]*v[1]+ans[2]*v[2]+ans[3]*v[3]+ans[4]*v[4]+ans[5]*v[5];
for(int i=0;i<6;i++) ///拆分成二进制
{
for(int j=1;j<=ans[i];j*=2)
{
v1[k++]=j*v[i];
ans[i] -= j;
}
if(ans[i] > 0)
v1[k++]=ans[i]*v[i];
}
printf("Collection #%d:\n",bj);
if(sum%2!=0) ///如果是奇数就没法平分
{
printf("Can't be divided.\n\n");
continue;
}
half=sum/2;
memset(dp,0,sizeof(dp));
for(int i=0;i<k;i++) ///01背包
for(int j=half;j>=v1[i];j--)
dp[j]=max(dp[j],dp[j-v1[i]]+v1[i]);
if(dp[half]==sum/2)
printf("Can be divided.\n");
else
printf("Can't be divided.\n");
printf("\n");
}
return 0;
}