poj1011 木棒 dfs+剪枝

目描述

乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

Input

输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。

Output

为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

Sample Input

9

5 2 1 5 2 1 5 2 1

4

1 2 3 4

0

Sample Output

6

5

 

做法很显然....就是dfs,枚举每一个长度来dfs,其他注意事项就在注释里面了


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[101],f=0,num,used[101];
int dfs(int N,int now)
{
	if(!now&&!N)return 1;//所有木棒都被选完了 
	if(!now)now=num;//组成了长度为now的一根木棒,开始找下一根木棒 
	for(int i=1;i<=n;i++)
	{
		if(!used[i]&&a[i]<=now)
		{
			if(i>1&&(!used[i-1]&&a[i-1]==a[i]))continue;//如果上一个没有选且这个个和上一个一样长那肯定也不选 
			used[i]=1;
			if(dfs(N-1,now-a[i]))return 1;
			else
			{
				used[i]=0;
				if(a[i]==now||now==num)return 0;//如果这一根不选,而且这一根还和剩余长度一样长,那么后面的肯定不能选了。如果这一根不选,而且还没有选,那么后面的就选不了了 
			}
		}
	}
	return 0;
}
int main()
{
	int i,j,k;
	while(scanf("%d",&n))
	{
		if(!n)break;
		int s=0,maxl=0;
		for(i=1;i<=n;i++)scanf("%d",&a[i]),s+=a[i];
		sort(a+1,a+1+n,greater<int>());
		for(num=a[1];num<=s/2;num++)//至多s/2的长度,不然就是s了 
		{
			if(s%num==0)//num必定是s因数 
			{
				memset(used,0,sizeof(used));	
				if(dfs(n,num))
				{
					printf("%d\n",num);
					break;
				}
			}
		}
		if(num>s/2)printf("%d\n",s);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/yslcl12345/article/details/50706094