当前位置:   article > 正文

【搜索】—— DFS之剪枝与优化_优化搜索顺序为什么能起到减枝的效果

优化搜索顺序为什么能起到减枝的效果


剪枝

剪枝,是为了减少搜索树规模,尽早排除搜索树中不必要的分支的一种手段。形象的说,就像是剪掉了搜索树的枝条,故称为“剪枝”。在深度优先搜索中,有以下几类常见的剪枝方式:

1.优化剪枝顺序

在一些搜索问题中,搜索树的各个层次、各个分支之间的顺序不是固定的。不同的搜索顺序会产生不同的搜索树形态,其规模大小也相差甚远。

以下的:

  1. 在“小猫爬山”问题中,把小猫按照重量递减的顺序进行搜索
  2. 在“数独”问题中,优先搜索“能填的合法数字”最少位置

2.排查等效冗余

在搜索过程中,如果我们能够判定从搜索树的当前节点上沿着几条不同分支到达子树是等效的,那么,只需对其中的一条分支执行搜索

3.可行性剪枝

在搜索过程中,及时对当前状态进行检查,如果发现分支已经无法到达递归边界,就执行回溯、这就好比我们在道路上行走,远远看到前方是一条死胡同,就应该立即折返绕路,而不是走到路的尽头再返回。

某些题目条件的范围限制是一个区间,此时可行性剪枝也被称为“上下界”剪枝

4.最优性剪枝

在最优化问题的搜索过程中,如果当前花费的代价已经超过了当前搜索到的最优解,那么无论采取多么优秀的策略到达递归边界,都不可能更新答案。此时可以停止对当前分支的搜索,执行回溯。

5.记忆化

可以记录每个状态的搜索结果,在重复遍历一个状态时直接检索并返回。这就好比我们对图进行深度优先遍历时,标记一个结点是否被访问过。


AcWing 165. 小猫爬山

输入样例:

  1. 5 1996
  2. 1
  3. 2
  4. 1994
  5. 12
  6. 29

输出样例:

2

来源:AcWing 165. 小猫爬山 - AcWing


  1. #include <cstring>
  2. #include <iostream>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 20;
  6. int n, m;
  7. int w[N];
  8. int sum[N];
  9. int ans = N;
  10. void dfs(int u, int k)
  11. {
  12. // 最优性剪枝
  13. if(k >= ans) return;
  14. if(u == n)
  15. {
  16. ans = k;
  17. return ;
  18. }
  19. for(int i = 0; i < k; i ++ )
  20. if(sum[i] + w[u] <= m)
  21. {
  22. sum[i] += w[u];
  23. dfs(u + 1, k);
  24. sum[i] -= w[u];
  25. }
  26. sum[k] = w[u];
  27. dfs(u + 1, k + 1);
  28. sum[k] = 0;
  29. }
  30. int main()
  31. {
  32. cin >> n >> m;
  33. for(int i = 0; i < n; i ++ ) cin >> w[i];
  34. // 优化搜索顺序
  35. sort(w, w + n);
  36. reverse(w, w + n);
  37. dfs(0, 0);
  38. cout << ans << endl;
  39. return 0;
  40. }

AcWing 166. 数独  

输入样例:

  1. 4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......
  2. ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
  3. end

输出样例:

  1. 417369825632158947958724316825437169791586432346912758289643571573291684164875293
  2. 416837529982465371735129468571298643293746185864351297647913852359682714128574936

 

  1. #include <cstring>
  2. #include <iostream>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 9, M = 1 << N;
  6. int ones[M], map[M];
  7. int row[N], col[N], cell[3][3];
  8. char str[100];
  9. void init()
  10. {
  11. for (int i = 0; i < N; i ++ )
  12. row[i] = col[i] = (1 << N) - 1;
  13. for (int i = 0; i < 3; i ++ )
  14. for (int j = 0; j < 3; j ++ )
  15. cell[i][j] = (1 << N) - 1;
  16. }
  17. void draw(int x, int y, int t, bool is_set)
  18. {
  19. if (is_set) str[x * N + y] = '1' + t;
  20. else str[x * N + y] = '.';
  21. int v = 1 << t;
  22. if (!is_set) v = -v;
  23. row[x] -= v;
  24. col[y] -= v;
  25. cell[x / 3][y / 3] -= v;
  26. }
  27. int lowbit(int x)
  28. {
  29. return x & -x;
  30. }
  31. int get(int x, int y)
  32. {
  33. return row[x] & col[y] & cell[x / 3][y / 3];
  34. }
  35. bool dfs(int cnt)
  36. {
  37. if (!cnt) return true;
  38. int minv = 10;
  39. int x, y;
  40. for (int i = 0; i < N; i ++ )
  41. for (int j = 0; j < N; j ++ )
  42. if (str[i * N + j] == '.')
  43. {
  44. int state = get(i, j);
  45. if (ones[state] < minv)
  46. {
  47. minv = ones[state];
  48. x = i, y = j;
  49. }
  50. }
  51. int state = get(x, y);
  52. for (int i = state; i; i -= lowbit(i))
  53. {
  54. int t = map[lowbit(i)];
  55. draw(x, y, t, true);
  56. if (dfs(cnt - 1)) return true;
  57. draw(x, y, t, false);
  58. }
  59. return false;
  60. }
  61. int main()
  62. {
  63. for (int i = 0; i < N; i ++ ) map[1 << i] = i;
  64. for (int i = 0; i < 1 << N; i ++ )
  65. for (int j = 0; j < N; j ++ )
  66. ones[i] += i >> j & 1;
  67. while (cin >> str, str[0] != 'e')
  68. {
  69. init();
  70. int cnt = 0;
  71. for (int i = 0, k = 0; i < N; i ++ )
  72. for (int j = 0; j < N; j ++, k ++ )
  73. if (str[k] != '.')
  74. {
  75. int t = str[k] - '1';
  76. draw(i, j, t, true);
  77. }
  78. else cnt ++ ;
  79. dfs(cnt);
  80. puts(str);
  81. }
  82. return 0;
  83. }

AcWing 167. 木棒 


输入样例:

  1. 9
  2. 5 2 1 5 2 1 5 2 1
  3. 4
  4. 1 2 3 4
  5. 0

输出样例:

  1. 6
  2. 5

 


AcWing 168. 生日蛋糕 

输入样例:

  1. 100
  2. 2

输出样例:

68

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/375399
推荐阅读
相关标签
  

闽ICP备14008679号