剪枝算法
大概理解是通过分析问题,发现一些判断条件,避免不必要的搜索。通常应用在DFS 和 BFS 搜索算法中;剪枝策略就是寻找过滤条件,提前减少不必要的搜索路径。
问题描述
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.
输入格式
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.
输出格式
The output should contains the smallest possible length of original sticks, one per line.
样例输入
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
样例输出
6
5
问题分析
题目意思:
乔治开始拿了a个长度均为L的木棍,随机锯木棍,最终把这a个木棍锯成了n个小块。根据n个小块及其各自长度,求出L可能的最小值。
如上图,根据右边的结果求出左边的L最小值为6(为什么要求最小值?因为L还可能为12,48)
剪枝条件分析:
1.a为整数,故初始长度L一定是总长度sum的因数。
2.n个小木块中,长度长的木块凑成L长的搭配可能性更小,所以将这n个木块从大到小排序,从大的开始搜索
3.搜索过程总按照排序,前一个小木棍没有成功时这一个也一定不能成功,直接略过
4.当一个木块拼凑失败时,直接回溯,不再按照这个条件搜索
#include
using namespace std;
#define MAX 65536
int a[MAX];
int vis[MAX];//是否已匹配的标志
int maxed;
int len; //木棍的数量
bool cmp(int x,int y)
{
return x>y;
}
//通过dfs判断是否可以拼凑成长度为k的木块
bool dfs(int sum,int cur,int res,int k) //k为假设的单个木块长度 ,res为已拼成木棍的数量 ,sum为当前正在拼凑的这一根木棍已有长度
{
if(res==maxed) //已成功拼完返回成功
{
return true;
}
for(int i=cur;i>len&&len)
{
sum=0;
for(int i=0;i>a[i];
sum+=a[i];
}
sort(a,a+len,cmp); //将木棍长度从大到小排序
int flag=0;
for(int i=a[0];i<=sum/2;i++)
{
if(sum%i==0) //可能的木棍的单独长度为sum的因子(因为初始为等长的完整的木棍
{
memset(vis,0,sizeof(vis)); //标记是否已用
maxed=sum/i; //可能的最多木棍数
if(dfs(0,0,0,i))
{
cout<
例子运行过程
eg:
输入:
9
5 2 1 5 2 1 5 2 1
输出:
6
代码转载自:https://blog.csdn.net/qq_36973725/article/details/84991602