【搜索】DFS迭代加深

目录

  • 迭代加深
    • 例题
      • 加成序列
        • 题意
        • 思路
        • 代码

迭代加深

搜索时可能会遇到这样一种情况:
【搜索】DFS迭代加深_第1张图片
明明答案就在第一层!但是因为DFS的缘故浪费很多时间
迭代加深就是用来解决这个问题的算法

定义一个 max_depth ,每次搜索时,超过这一层就全部剪掉、
(相当于我们划定一个区域,在这个区域内找解,如果找不到,再扩大区域)

?迭代加深和BFS有什么区别呢
BFS用队列存储,浪费空间,迭代加深本质是还是DFS,只存储本条路径,还是O(n)的算法

例题

加成序列

原题链接

满足如下条件的序列 X(序列中元素被标号为 1、2、3…m)被称为“加成序列”:

  1. X [ 1 ] = 1 X[1]=1 X[1]=1
  2. X [ m ] = n X[m]=n X[m]=n
  3. X [ 1 ] < X [ 2 ] < … < X [ m − 1 ] < X [ m ] X[1]X[1]<X[2]<<X[m1]<X[m]
  4. 对于每个 k(2 ≤ k ≤ m)都存在两个整数 i 和 j (1 ≤ i , j ≤ k − 1,i 和 j 可相等),使得 X [ k ] = X [ i ] + X [ j ] X[k]=X[i]+X[j] X[k]=X[i]+X[j]

你的任务是:给定一个整数 n,找出符合上述条件的长度 m 最小的“加成序列”。

如果有多个满足要求的答案,只需要找出任意一个可行解。

输入格式

输入包含多组测试用例。

每组测试用例占据一行,包含一个整数 n。

当输入为单行的 0 时,表示输入结束。

输出格式

对于每个测试用例,输出一个满足需求的整数序列,数字之间用空格隔开。

每个输出占一行。

数据范围

1 ≤ n ≤ 100

输入样例

5
7
12
15
77
0

输出样例

1 2 4 5
1 2 4 6 7
1 2 4 8 12
1 2 4 5 10 15
1 2 4 8 9 17 34 68 77

题意

给出 n 构造一个序列,要求第一个数是1,最后一个数是n,严格递增,且后面的数一定要是前面两个数之和(两个数可以是同一个数),输出一个长度最小的序列

思路

序列的最小规模:1 2 4 8 16 32 64 128 此时就已经超过100了,说明正确答案的深度不会很深,适合用迭代加深来做
层数从1开始,依次考虑每一位选什么数字

优化:

  1. 优化搜索顺序:优先枚举较大的数,层数较少,更快的找到 n
  2. 排除等效冗余:举个栗子:1 2 3 4 现在枚举下一个数,不管选择1+4还是2+3结果都是5,就可以不用计算两次了(方法是开一个bool数组存储每个数是否被用过)

代码

#include 

using namespace std;

const int N = 110;

int n;
int path[N];
bool st[N]; // 标记某数是否被用过

bool dfs(int u, int depth) // 分别是当前层数和最大层数
{
    if (u > depth) return false; // 当前层数>最大层数
    if (path[u - 1] == n) return true; // 最后一个数为n满足条件

    for (int i = u - 1; i >= 0; i -- )
        for (int j = i; j >= 0; j -- )
        {
            int s = path[i] + path[j];
            if (s > n || s <= path[u - 1] || st[s]) continue; // 大于最大值or小于前一个值or已被用过 都不满足条件

            st[s] = true; // 标记s已被用过
            path[u] = s; // 记录s
            if (dfs(u + 1, depth)) return true; // 下一位
            st[s] = false; // 恢复现场
        }

    return false;
}

int main()
{
    path[0] = 1;
    while (cin >> n, n)
    {
        memset(st, false, sizeof st);
        int depth = 1;
        while (!dfs(1, depth)) depth ++ ;
        for (int i = 0; i < depth; i ++ ) cout << path[i] << ' ';
        cout << '\n';
    }
}

你可能感兴趣的:(搜索,深度优先,迭代加深,算法)