题解 UVA307 【Sticks】

题目链接:Link

Solution

做这题时我借鉴了某一大佬的博客:传送门
在这里我就把原文解释一下(详见代码):

#include<cstdio>
#include<cstring>
const int N=70;
int n,cnt,tot,maxn,minn,tm[N]; 
bool ok;
void dfs(int need,int sum,int goal,int maxlen)
{
	if(need==0)//找到了
	{
		printf("%d\n",goal);
		ok=true;
	}
	if(sum==goal)//拼完了一根 
	{
		dfs(need-1,0,goal,maxn);
		return;
	}
	for(int i=maxlen;i>=minn;i--)//用单调性确保不重复 
		if(tm[i]&&i+sum<=goal)
		{
			tm[i]--;
			dfs(need,sum+i,goal,i);
			if(ok) return;
			tm[i]++;
			if(sum==0||sum+i==goal) break;
            //如果刚好凑整的组合方式都不行,别的就更不行。
		}
}
int main()
{
#ifdef local
	freopen("pro.in","r",stdin);
#endif
	while(scanf("%d",&n)==1&&n)
	{
		minn=N ;
		int x;
		cnt=tot=maxn=0;
		memset(tm,0,sizeof(tm));
		while(n--)
		{
			scanf("%d",&x);
			if(x<=50)
			{
				cnt++;
				tm[x]++;//用桶更方便 
				tot+=x;
				maxn=maxn>x?maxn:x;
				minn=minn<x?minn:x;
			}
		}
		x=tot/2;//tot一定可以,能算不举
		ok=false;
		for(int i=maxn;i<=x;i++)
			if(tot%i==0)
			{
				dfs(tot/i,0,i,maxn);
				if(ok) break;
			}
		if(!ok) printf("%d\n",tot);
	}
	return 0;
}
posted @ 2019-08-19 21:50  happyZYM  阅读(103)  评论(0编辑  收藏  举报