仍然是多重背包,判断能否恰好装满总值的一半即可。自己写的代码太烂,跑了700ms。本题当然也可以用母函数来写。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxm=60005;
int f[maxm];
int s[10];
int max(int x,int y)
{
return x>y?x:y;
}
void work()
{
int i,j,k,sum,ans;
memset(f,0,sizeof(f));
sum=0;
for(i=1;i<=6;i++) sum+=i*s[i];
for(i=1;i<=6;i++)
{
if(i*s[i]>sum/2+1)
{
for(j=i;j<=sum/2+1;j++)
f[j]=max(f[j],f[j-i]+i);
}
else
{
k=1;
while(k<s[i])
{
for(j=sum/2+1;j>=i*k;j--)
f[j]=max(f[j],f[j-i*k]+i*k);
s[i]-=k;
k<<=1;
}
for(j=sum/2+1;j>=i*s[i];j--)
f[j]=max(f[j],f[j-i*s[i]]+i*s[i]);
}
}
ans=(f[sum/2]==sum/2);
if(sum&1) ans=0;
printf(ans?"Can be divided.\n":"Can't be divided.\n");
printf("\n");
}
int main()
{
int i,sum,T;
T=0;
do
{
sum=0;
for(i=1;i<=6;i++)
{
scanf("%d",&s[i]);
sum+=s[i];
}
if(sum==0) break;
printf("Collection #%d:\n",++T);
work();
}
while(sum!=0);
return 0;
}