• 【搜索】—— 迭代加深/双向DFS/IDA*



    迭代加深 

    深度优先搜索每次固定选定一个分支,不断深入,直到达到递归边界才回溯。这种策略带有一定的缺陷,假设有以下情况:搜索树每个结点的分支很多,并且问题的答案在一个较浅的结点上。如果深搜在一开始选错了分支,就很可能在不包含答案的深层子节树上浪费许多时间。

    如下图所示,左半部分是问题的状态空间,菱形表示答案,那么深度优先搜索产生的搜索树如下图所示,算法在矩阵圈出的深层子树上浪费了许多时间。

    此时,我们可以从小到大限制搜索的深度,如果在当前深度下搜索不到答案,就把深度限制增加,重新进行一次搜索,这就是迭代加深的思想。 


    虽然该过程在深度限制为 d 的时候,会重复搜索 1~d-1 层的结点,但是当搜索数节点分支数目较多的时,随着层数的深入,每层节点会呈指数级增长,这点重复搜索和深层子树的规模相比,就是小巫见大巫了。 

    总而言之,当搜索树规模随着层次的深入增长很快,并且我们能够保证答案在一个较浅层次的节点的时候,就可以采用迭代加深的深度优先搜索算法来解决问题。


    AcWing 170. 加成序列 

     

    输入样例:

    1. 5
    2. 7
    3. 12
    4. 15
    5. 77
    6. 0

    输出样例:

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

    剪枝1:优先枚举较大的数

    剪枝2:排除等效冗余


    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N = 110;
    6. int n;
    7. int path[N];
    8. bool dfs(int u, int depth)
    9. {
    10. if(u > depth) return false;
    11. if(path[u - 1] == n) return true;
    12. bool st[N] = {0};
    13. for(int i = u - 1; i >= 0; i -- )
    14. for(int j = i; j >= 0; j --)
    15. {
    16. int s = path[i] + path[j];
    17. if(s > n || s <= path[u - 1] || st[u]) continue;
    18. st[s] = true;
    19. path[u] = s;
    20. if(dfs(u + 1, depth)) return true;
    21. }
    22. return false;
    23. }
    24. int main()
    25. {
    26. path[0] = 1;
    27. while(cin >> n, n)
    28. {
    29. int depth = 1;
    30. while(!dfs(1, depth)) depth ++ ;
    31. for(int i = 0; i < depth ; i ++ ) cout << path[i] << ' ';
    32. cout << endl;
    33. }
    34. return 0;
    35. }

    AcWing 171. 送礼物 (双向DFS)

    输入样例:

    1. 20 5
    2. 7
    3. 5
    4. 4
    5. 18
    6. 1

    输出样例:

    19

    1. 将所有的物品按照重量从小到大排序
    2. 先将前K件物品能凑出的所有重量打表,然后排序并判重
    3. 搜索剩下的N-K件物品的选择方式,然后在表中二分出不超过W的最大值

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. typedef long long LL;
    6. const int N = 1 << 24;
    7. int n, m, k;
    8. int g[50], weights[N];
    9. int cnt = 0;
    10. int ans;
    11. void dfs(int u, int s)
    12. {
    13. if (u == k)
    14. {
    15. weights[cnt ++ ] = s;
    16. return;
    17. }
    18. if ((LL)s + g[u] <= m) dfs(u + 1, s + g[u]);
    19. dfs(u + 1, s);
    20. }
    21. void dfs2(int u, int s)
    22. {
    23. if (u == n)
    24. {
    25. int l = 0, r = cnt - 1;
    26. while (l < r)
    27. {
    28. int mid = l + r + 1 >> 1;
    29. if (weights[mid] + (LL)s <= m) l = mid;
    30. else r = mid - 1;
    31. }
    32. if (weights[l] + (LL)s <= m) ans = max(ans, weights[l] + s);
    33. return;
    34. }
    35. if ((LL)s + g[u] <= m) dfs2(u + 1, s + g[u]);
    36. dfs2(u + 1, s);
    37. }
    38. int main()
    39. {
    40. cin >> m >> n;
    41. for (int i = 0; i < n; i ++ ) cin >> g[i];
    42. sort(g, g + n);
    43. reverse(g, g + n);
    44. k = n / 2; // 防止 n = 1时,出现死循环
    45. dfs(0, 0);
    46. sort(weights, weights + cnt);
    47. int t = 1;
    48. for (int i = 1; i < cnt; i ++ )
    49. if (weights[i] != weights[i - 1])
    50. weights[t ++ ] = weights[i];
    51. cnt = t;
    52. dfs2(k, 0);
    53. cout << ans << endl;
    54. return 0;
    55. }

  • 相关阅读:
    在 Django Model ViewSet 中实现多对多字段的搜索
    如何在公司内部统一「数据指标口径」?_光点科技
    ChatGPT DAN 模式
    算法基础学习|二分
    dvwa命令执行漏洞分析
    msvc++中的预编译头文件pch.hpp和stdafx.h
    vscode配置调用visual studio的编译和调试环境
    LibPca--Packet Capture library
    排序算法练习及应用..
    四大含金量高的算法证书考试
  • 原文地址:https://blog.csdn.net/forever_bryant/article/details/126026889