POJ1014 Dividing

Description

link

有价值为\(1,2,3,4,5,6\)的六种硬币,每种硬币有给定个,求是不是存在一种分配的方案使得两堆中的价值相等

\(num \le 2 \times 10^4\)

Solution

我们发现如果有一组情况是满足 \(sum=\frac{\sum\limits_{i=1}^{6} i \times a_i}{2}\)

那么剩下的那组就也可以构成 \(\frac{\sum\limits_{i=1}^{6} i \times 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:\n",++cnt); puts("Can't be divided.\n"); 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:\n",++cnt); puts(f[sum]>=0?"Can be divided.\n":"Can't be divided.\n");
		}
		return 0;
	}
}
signed main(){return yspm::main();}

Review

依序做题:定义状态,找状态转移

猜你喜欢

转载自www.cnblogs.com/yspm/p/12735618.html