题目描述
玛莎和比尔各自有自己的弹珠收藏。他们想重新分配收藏品,使两人能平等拥有弹珠。如果所有的弹珠的价值相同,那么他们就可以平分。但不幸的是,有一些弹珠更大,或者更美丽,所以,玛莎和比尔给每个弹珠一个1到6的价值。现在他们想平分这些弹珠,使每个人得到的总价值相同。不幸的是,他们发现,他们可能无法以这种方式分弹珠(即使弹珠的总价值为偶数)。例如,如果有一个价值为1、一个价值为3和两个价值为4的弹珠,这样他们就不能把弹珠分为价值相等的两部分。因此,他们想要你写一个程序,告诉他们是否能将所有弹珠分成价值相等的两部分。
输入输出格式
输入格式:输入文件有若干行,行中包含六个非负整数N1,。..,N6,其中mi是数值i的弹珠的价值。最大弹珠总数将达到20000。
输入文件的最后一行是0 0 0 0 0 0 。不要处理这一行。
输出格式:对于每一组数据,输出"Collection #k:", k为输出的是第几组, 接着是"Can be divided." 或 "Can't be divided.".
每一组输出后多打一个空行。
这道题我用了多重背包来做,因为担心超时又加了二进制优化,不是难题但是一遍通过还是很舒服的。
只要判断所给的球能否组成总价值的一般即可!!
代码:#include <cstdio>
#include <algorithm>
using namespace std;
int a[7],b[20001],dp[1008611];
int main()
{
int i,j,sum,k,t,cou=1;
while(1)
{
sum=0;
t=0;
for(i=1;i<=6;i++)
{
scanf("%d",&a[i]);
sum+=a[i]*i;
k=1;
while(k<a[i])
{
b[t++]=k*i;
a[i]-=k;
k*=2;
}
b[t++]=a[i]*i;
}
if(sum==0)
break;
if(sum%2!=0)
{
printf("Collection #%d:\n",cou++);
printf("Can't be divided.\n");
printf("\n");
continue;
}
int ans=sum/2;
for(i=0;i<t;i++)
for(j=ans;j>=b[i];j--)
{
dp[j]=max(dp[j-b[i]]+b[i],dp[j]);
}
if(dp[ans]==ans)
{
printf("Collection #%d:\n",cou++);
printf("Can be divided.\n");
printf("\n");
}
else
{
printf("Collection #%d:\n",cou++);
printf("Can't be divided.\n");
printf("\n");
}
}
return 0;
}
#include <algorithm>
using namespace std;
int a[7],b[20001],dp[1008611];
int main()
{
int i,j,sum,k,t,cou=1;
while(1)
{
sum=0;
t=0;
for(i=1;i<=6;i++)
{
scanf("%d",&a[i]);
sum+=a[i]*i;
k=1;
while(k<a[i])
{
b[t++]=k*i;
a[i]-=k;
k*=2;
}
b[t++]=a[i]*i;
}
if(sum==0)
break;
if(sum%2!=0)
{
printf("Collection #%d:\n",cou++);
printf("Can't be divided.\n");
printf("\n");
continue;
}
int ans=sum/2;
for(i=0;i<t;i++)
for(j=ans;j>=b[i];j--)
{
dp[j]=max(dp[j-b[i]]+b[i],dp[j]);
}
if(dp[ans]==ans)
{
printf("Collection #%d:\n",cou++);
printf("Can be divided.\n");
printf("\n");
}
else
{
printf("Collection #%d:\n",cou++);
printf("Can't be divided.\n");
printf("\n");
}
}
return 0;
}
刷题还是有效果的,继续努力!