Description
有价值为(1,2,3,4,5,6)的六种硬币,每种硬币有给定个,求是不是存在一种分配的方案使得两堆中的价值相等
(num le 2 imes 10^4)
Solution
我们发现如果有一组情况是满足 (sum=frac{sumlimits_{i=1}^{6} i imes a_i}{2})
那么剩下的那组就也可以构成 (frac{sumlimits_{i=1}^{6} i imes a_i}{2})
我们比较直观的可以想到一个传递存在性的方法
但是会 (T) 飞
定义状态:(f_{i,j}) 表示前 (i) 个数字凑出 (j) 最多还剩下多少硬币
转移显然……
怎么跟那个分手是问候一个样……
最后判断(f_{sum} ge 0) 即可
最后请注意你的输出有没有点
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=10;
int a[N],n,cnt;
int f[200010];
signed main()
{
while(1)
{
int sum=0;
for(int i=1;i<=6;++i) a[i]=read(),sum+=a[i]*i;
if(!sum) break;
if(sum%2){printf("Collection #%lld:
",++cnt); puts("Can't be divided.
"); continue;}
sum/=2; for(int i=0;i<=sum;++i) f[i]=-1; f[0]=0;
for(int i=1;i<=6;++i)
{
for(int j=0;j<=sum;++j)
{
if(f[j]>=0) f[j]=a[i];
else
{
if(j<i||f[j-i]<=0) f[j]=-1;
else f[j]=f[j-i]-1;
}
} if(f[sum]>=0) break;
}
printf("Collection #%lld:
",++cnt); puts(f[sum]>=0?"Can be divided.
":"Can't be divided.
");
}
return 0;
}
}
signed main(){return yspm::main();}
Review
依序做题:定义状态,找状态转移