Sticks(经典深搜)

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 file 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

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int cmp(const int a, const int b) {
	return a > b;
}
int n,len;
int a[65],flag[65];
int DFS(int pos,int l,int s)
{
	//if(pos>n) return 0;
	int i,j;
	if(l==0)  //说明有一根原始木棍被拼揍成功,接下来拼凑下一根; 
	{
		s-=len;
		if(s==0) return 1;
		for(i=0;;i++)   //得再接着找木棍拼凑
		{
			if(flag[i]==0)
			{
				flag[i]=1;
				break;
			}
		}
		 //选择了下标为i的木棍
		
		if(DFS(i+1,len-a[i],s)) return 1; //如果接下来的搜索成功,说明可以全部拼凑成功
		
		s+=len; //能走到这一步,说明接下来的搜索没成功 
		flag[i]=0;
		return 0; //既然没成功,那么就说明初始长度为这个len不能拼凑成功,换下一个len 
	}
	else //还得接着凑成完整一根 
	{
		for(i=pos;i<n;i++) //接着在剩余的棒子中找 
		{
			if(i>0 && a[i]==a[i-1] && flag[i-1]==0) //这个剪枝很重要,就是我在凑棍子的时候,如果我之前那根不行,那么后边和他长度
			//相同的棍子肯定也不行,听说这个剪枝使原来的TLE一下变成16MS,看来hack点就在这啊。 
			{
				continue;
			 } 
			if(a[i]<=l && !flag[i]) //首先得保证目前找的这根棍子不能比还需凑得长度要大,另外这根棍子得之前没有被选过 
			{
				flag[i]=1;
				l-=a[i];
				if(DFS(i+1,l,s)) return 1;
				
				flag[i]=0;
				l+=a[i]; 
			}
		 } 
		 return 0; //如果找遍所有棍子都无法凑成原始长度,那么返回0; 
	}
}
int main()
{
	int i,j,sum=0,tap;
	while(~scanf("%d",&n) && n)
	{
		sum=0;
		tap=0;
		for(i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			sum+=a[i];
		}
		sort(a,a+n,cmp);
		for(len=a[0];len<=sum/2;len++)
		{
			memset(flag,0,sizeof(flag));
			if(sum%len==0 && DFS(0,len,sum))   //我首先得说明这两个判断条件先后顺序的重要性!!!!你如果反了,一直是TLE 
			{
				tap=1;
				printf("%d\n",len);
				break;
			}
		}
		if(!tap) printf("%d\n",sum);
	}
	return 0;
}


这是看大佬的代码,看的第一遍看的迷迷糊糊的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值