POJ-1011(sticks,深搜)

Description

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.

Input

The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.

Output

The output should contains the smallest possible length of original sticks, one per line.

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

分析:

  • 先存大的棍子,对于每一次搜索,关心的状态有三个:现在拼的棍子是第几个,已经拼了多少了,上次拼的那根是序列中的第几根
  • 如果拼当前棍子的时候,拼了一个长度为a的棍子,发现失败了,那么之后就不用再尝试长度为a的棍子了
  • 如果现在要拼的棍子长度为0,然后发现有一个棍子试图去拼然后失败了,那么这条路子就是错的,因为最终肯定不会全部拼完整,
  • 同理,如果刚好拼好一根棍子,发现接下来再拼失败了,那么接下来也没办法成功拼完整的。
int a[100],v[100],n,cnt,len;

bool cmp(int a,int b)
{
	return a>b;
}
bool dfs(int stick,int cab,int last)
{
	if(stick == cnt+1)
		return true;
	if(cab == len)
		return dfs(stick+1,0,1);//这里第一次忘记return了,好坑
	int fail = 0;
	for(int i=last;i<=n;i++)
	{
		if(!v[i]&&cab+a[i]<=len&&fail!=a[i])
		{
			v[i] = 1;		if(dfs(stick,cab+a[i],i+1))
				return true;
			fail = a[i];
			v[i] = 0;
		    //如上述最后两条所说
		    if(cab==0||cab+a[i]==len)
				return false;
		}
	}
	return false;
}
int main() 
{
    while(cin>>n,n)
    {
    	int sum = 0,val = 0;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		sum+=a[i];
    		val = max(val,a[i]);
    	}
    	sort(a+1,a+1+n,cmp);
    	for(len = val;len<=sum;len++)
    	{
    		if(sum%len)continue;
    		cnt = sum/len;
    		//cout<<cnt<<endl;
    		memset(v,0,sizeof v);
    		if(dfs(1,0,1))break;
    	}
    	cout<<len<<endl;
    }
    return 0;
}
posted @ 2018-08-16 17:11  kpole  阅读(267)  评论(0编辑  收藏  举报