深搜的剪枝技巧—小木棍

时间限制: 1 Sec  内存限制: 128 MB

题目描述

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。

现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。

给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。

输入

输入文件共有二行。

第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤60。

第二行为N个用空个隔开的正整数,表示N根小木棍的长度。

输出

输出文件仅一行,表示要求的原始木棍的最小可能长度。

样例输入

9

5 2 1 5 2 1 5 2 1

样例输出

6

题解:

可以依次枚举所有可能的长度len,用深搜判断是否能用截断后所有的小木棍拼出整数个len,找出最小的len

最优性剪枝:

1、设所有木棍的长度和是sum,那么原长度一定能够被sum整除,不然就没法拼了

2、木棍原来的长度一定大于等于所有木棍中最长的那根

可行性剪枝:

3、短小的木棍可以更灵活,可以对输入的木根从大到小排序

4、当用木棍i拼合时,可以从第i+1后的木棍开始搜索,因为根据优化1,前面的木棍已经用过了

5、用当前最长的木棍开始搜索,如果拼不出当前设定的原木棍的长度,则直接返回,换一个原始木根长度

6、相同长度的木棍不要搜索多次,用当前木棍的长度搜下去得不到结果时,用一支同样长度的还是得不到结果,所以,可以提前返回

7、判断搜到的几根木棍组成的长度是否大于原始长度len,如果大于,没必要搜下去,提前返回

#include 
#include 
#include 
using namespace std;
int n,sum=0,a[60],len,m,temp,minn=0,used[60];
bool cmp(int x,int y)
{
	return x>y;
}
void read()
{
	cin>>n;
	for (int i=0;i>a[i];
		sum+=a[i];
    }
    sort(a,a+n,cmp);                 //剪枝3,从大到小排序,长木棍的灵活性差,先排长木棍 
}
void dfs(int k,int last,int rest)   //第k根木棍,last为第k根上一节木棍编号,rest为第k根木棍还需要的长度 
{
	if (k==m) {temp=1;return;}
	if (rest==0)                    //开始下一根木棍 
	{
		int i;
		for (i=0;i=a[i])   //木棍未被访问过,且比需要的木棍长度小
		{
			used[i]=1;
			dfs(k,i,rest-a[i]); 
			used[i]=0;              //回溯 
			j=i;                    //记录当前的木棍的编号 
			while (i

 

你可能感兴趣的:(搜索:)