在深度优先搜索当中,是一条路走到底,但是当每个结点元素的分支非常多时,找到目标元素就会浪费很多搜索的时间。则引入层数限制
最大搜索层数限制:当限制层数depth=1时,仅进行最大层数为1的深度优先遍历,当达到depth仍未搜索到时则为搜索失败,层数加一再次进行搜索。
问:每次层数的增加都要从头再进行搜索,是否会浪费搜索时间?
答:
题意:序列长度为m;首元素:1,尾元素:n,在首尾之间补充m-2个元素(递增)。
限制条件:任意的k(2≤k≤m)都存在序列中两个下标为i、j的元素满足X[k]=X[i]+X[j]
输入:每行一个尾元素n,以0为结尾。
输出:长度最短的解
剪枝:1.bool数组标记,排除冗余(避免重复搜索同一个和) 2.从大到小枚举(快速逼近n)
思路:限制层数从1开始,用path数组记录。
#include <iostream>
using namespace std;
int path[110];
bool mark[110];
int n;
/*
在搜索的时候限制搜索的最大深度
设当前的最大深度为depth 当没找到的时候 depth+1再次搜索
有效节省搜索的时间
限制:
1首尾元素
2严格递增
3每个数都是前面某两个数的和(可以重复)
得到长度最短的合法方案
*/
//u表示当前层数 k表示限制层数
bool dfs(int u,int k){
//当达到最大层数
if(u==k){
return path[u-1]==n;//判断最后一位是否到
}
//从大到小进行枚举
for(int i=u-1;i>=0;i--){
for(int j=i;j>=0;j--){
int s=path[i]+path[j];
//当s超出范围 小于前一个数 s已经出现过了
if(s>n||s<=path[u-1]||mark[s]){
continue;
}
mark[s]=true;//标记当前的数字
path[u]=s;
if(dfs(u+1,k)){
return true;
}
}
}
}
int main(){
//初始头为1 结尾
path[0] = 1;
//当n不为0时
while (cin >> n, n) {
int k = 1;//初始限制的层次为1
//当
while (!dfs(1, k)) { // 不断扩大范围
k++;//层次限制加一
}
//输出路径
for (int i = 0; i < k; i++) {
cout << path[i] << " ";
}
cout << endl;
}
return 0;
}