回溯法:八皇后问题

蔚落 2022-08-08 12:45 289阅读 0赞

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

这个问题简化描述就是:在8x8的棋盘上放8颗子,要求它们【不在同一行】【不在同一列】【不在同一斜线】上。
我们可以定义一个数组position[8],positon[i]=j代表第i行摆在第j列。所以我们的约束条件可以进行如下表示:

  1. 不在同一列:position[i] ≠ position[j]
  2. 不在同一主对角线:position[i] - i ≠ position[j] - j
  3. 不在同一副对角线:position[i] + i ≠ position[j] + j
    其中2和3可以合并成abs(i - j) ≠ abs(position[i] - position[j])

求解思路:
首先从第一个皇后开始,从第一行确定第一个皇后位置,然后再在第二行搜索第二个 皇后位置……没前进一步检查是否满足约束条件,不满足的时候回溯到上一个皇后位置,尝试该行的其他列是否满足条件,直到找到问题的解。

C++参考代码:

  1. #include <iostream>
  2. using namespace std;
  3. const int N = 8;//皇后的个数
  4. int positon[N];//存放皇后的位置
  5. int count = 0;//记录有多少种摆法
  6. /*判断第row行放置的位置是否满足要求*/
  7. bool valid(int row)
  8. {
  9. for (int i = 0; i < row; ++i)
  10. {
  11. // 如果和前面放好位置的不在同一列,也不在对角线上,则返回true,否则返回false
  12. if (positon[i] == positon[row] || abs(positon[i] - positon[row]) == abs(i - row))
  13. return false;
  14. }
  15. return true;
  16. }
  17. /*输出摆放结果*/
  18. void print()
  19. {
  20. cout << "这是第" << ++count << "种摆法:" << '\n';
  21. for (int i = 0; i < N; ++i)
  22. {
  23. for (int j = 0; j < N; ++j)
  24. {
  25. if (positon[i] == j)
  26. cout << "⊙ ";
  27. else
  28. cout << "× ";
  29. }
  30. cout << '\n';
  31. }
  32. cout << endl;
  33. }
  34. /*回溯法搜索摆放位置*/
  35. void trail(int row = 0)
  36. {
  37. // 如果摆完完N行,则输出结果
  38. if (N == row)
  39. {
  40. print();
  41. return;
  42. }
  43. for (int column = 0; column < N; ++column)
  44. {
  45. positon[row] = column;// 放置在第row行第column列
  46. // 如果满足条件,则进行下一行
  47. if (valid(row)) trail(row + 1);
  48. // 如果不满足条件,则进行下一次循环,即回溯回去在第row行重新寻找摆放的位置
  49. }
  50. }
  51. int main()
  52. {
  53. trail();
  54. return 0;
  55. }

总共有92种摆法:
运行结果


下面官方的说一下回溯法(摘自百度百科)。
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

基本思想:
在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束

发表评论

表情:
评论列表 (有 0 条评论,289人围观)

还没有评论,来说两句吧...

相关阅读

    相关 回溯-N皇后问题

    一、N皇后问题 n皇后问题:要求在一个n×n的棋盘上放置n个皇后,使得任意两个皇后不在同一行或同一列或同一斜线上。 二、回溯法 回溯法是一类非常重要的算法设计方法

    相关 回溯皇后问题

    八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横

    相关 皇后问题(回溯)

    问题描述: 在8\8的棋盘上,放置8个皇后,使他们互相不攻击; 解析: 进行逐行放置,皇后肯定不会进行横向攻击,因此只需检查纵向和斜向是否会进行攻击即可 代码:  C

    相关 皇后问题回溯

    问题描述 ![70][] 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上(与水平行轴成45°或135°),问有多少

    相关 回溯皇后

    回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再

    相关 回溯—— / N 皇后问题

    回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。 回溯法在问题的解空间树中,按深度优先策略,从根结点