回溯法 之 八皇后问题

来源:互联网 发布:能写出这样的句子 知乎 编辑:程序博客网 时间:2024/05/16 00:55

原文链接:http://blog.csdn.net/crayondeng/article/details/17174557

回溯法

回溯法有“通用的解题法”之称。用它可以系统地搜索一个问题的所有解或任一解。回溯法是一种即带有系统性又带有跳跃性的搜索算法。它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一结点时,先判断该节点是否包含问题的解。如果不包含,则跳过对以该节点为根的子树的搜索,逐层向其它祖先节点回溯。否则,进入该子树,继续按照深度优先策略搜索。回溯法求问题的所有解时,要回溯到根,且根节点的所有子树都已被搜索遍才结束。回溯法求问题的一个解时,只要搜索到问题的一个解就可结束。这种以深度优先方式系统搜索问题的算法称为回溯法,它是用于解组合数大的问题。

回溯法的基本思想

确定了解空间的组织结构后,回溯法从根节点出发,以深度优先搜索方式搜索整个解空间。回溯法以这种工作方式递归地在解空间中搜索,直到找到所要求的解或解空间所有解都被遍历过为止。
回溯法搜索解空间树时,通常采用两种策略避免无效搜索,提高回溯法的搜索效率。其一是用约束函数在当前节点(扩展节点)处剪去不满足约束的子树;其二是用限界函数剪去得不到最优解的子树。这两类函数统称为剪枝函数。

回溯法解题通常包含以下三个步骤:

1.针对所给问题,定义问题的解空间;
2.确定易于搜索的解空间结构;
3.以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。


回溯法的实现

有两种方法:递归回溯和迭代回溯(非递归实现)
下面给出这两个回溯实现的一般方法。

递归回溯:



迭代回溯:




在回溯法中有一个经典的问题八皇后问题

---- 以下有关八皇后问题介绍来着wikipedia。

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

历史

八皇后问题最早是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出。之后陆续有数学家对其进行研究,其中包括高斯和康托,并且将其推广为更一般的n皇后摆放问题。八皇后问题的第一个解是在1850年由弗朗兹·诺克给出的。诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。

艾兹格·迪杰斯特拉在1972年用这个问题为例来说明他所谓结构性编程的能力[2]

八皇后问题在1990年代初期的著名电子游戏第七访客和NDS平台的著名电子游戏雷顿教授与不可思议的小镇中都有出现。

八皇后问题的解

八皇后问题一共有 92 个互不相同的解。如果将旋转和对称的解归为一种的话,则一共有12个独立解,具体如下:

Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解1
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解2
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解3
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解4
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解5
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解6
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解7
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解8
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解9
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解10
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解11
Chess zhor 26.svgChess zver 26.svga8b8c8d8e8f8g8h8a7b7c7d7e7f7g7h7a6b6c6d6e6f6g6h6a5b5c5d5e5f5g5h5a4b4c4d4e4f4g4h4a3b3c3d3e3f3g3h3a2b2c2d2e2f2g2h2a1b1c1d1e1f1g1h1Chess zver 26.svgChess zhor 26.svg独立解12

解的个数

下表给出了 n 皇后问题的解的个数包括独立解U(OEIS中的数列A002562)以及互不相同的解D(OEIS中的数列A000170)的个数:

n1234567891011121314..242526U:10012161246923411,7879,23345,752..28,439,272,956,934275,986,683,743,4342,789,712,466,510,289D:100210440923527242,68014,20073,712365,596..227,514,171,973,7362,207,893,435,808,35222,317,699,616,364,044

可以注意到六皇后问题的解的个数比五皇后问题的解的个数要少。现在还没有已知公式可以对 n 计算 n 皇后问题的解的个数。



下面正式进入编程阶段咯:

在下面的代码中给出了递归方法实现和迭代方法实现的八皇后问题!

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cmath>  
  3. #include <cstring>  
  4. using namespace std;  
  5.   
  6. int queen[9];  
  7.   
  8. //数组初始化  
  9. void init()  
  10. {  
  11.     memset(queen,0,9*sizeof(int));  
  12. }  
  13.   
  14. //输出结果  
  15. void print()  
  16. {  
  17.     for(int i=1; i<9; i++) cout<<queen[i]<<"  ";  
  18.     cout<<endl;  
  19. }  
  20.   
  21. //剪枝函数  
  22. bool canPlaceQueen(int k)  
  23. {  
  24.     for(int i = 1; i < k; i++)  
  25.     {  
  26.         //判断是否处于同一列或同一斜线  
  27.         if(queen[i] == queen[k] || abs(k-i) == abs(queen[k]-queen[i])) return false;  
  28.     }  
  29.     return true;  
  30. }  
  31. //迭代方法求解八皇后过程  
  32. void eightQueen_1()  
  33. {  
  34.     int k = 1;  
  35.     while(k>=1)  
  36.     {  
  37.         while(queen[k]<=7)  
  38.         {  
  39.             queen[k] += 1;  
  40.             if(k == 8 && canPlaceQueen(k))  
  41.             {  
  42.                 print();  
  43.             }  
  44.             else if(canPlaceQueen(k))  
  45.             {  
  46.                 k++;  
  47.             }  
  48.         }  
  49.         queen[k] = 0;  
  50.         k--;  
  51.     }  
  52. }  
  53.   
  54. //递归方法求解八皇后过程  
  55. void eightQueen_2(int k)  
  56. {  
  57.     for(int i=1; i<9; i++)  
  58.     {  
  59.         queen[k] = i;  
  60.         if(k == 8 && canPlaceQueen(k))  
  61.         {  
  62.             print();  
  63.             return;  
  64.         }  
  65.         else if(canPlaceQueen(k))  
  66.         {  
  67.             eightQueen_2(k+1);  
  68.         }  
  69.     }  
  70. }  
  71. int main()  
  72. {  
  73.     init();  
  74.     eightQueen_1();  
  75. //    eightQueen_2(1);  
  76.     return 0;  
  77. }  

过程比较简单,就不多细说了,关于n皇后问题,通过对上面代码的稍加改动也可以实现。

运行输出结果:
[cpp] view plain copy
  1. 1  5  8  6  3  7  2  4  
  2. 1  6  8  3  7  4  2  5  
  3. 1  7  4  6  8  2  5  3  
  4. 1  7  5  8  2  4  6  3  
  5. 2  4  6  8  3  1  7  5  
  6. 2  5  7  1  3  8  6  4  
  7. 2  5  7  4  1  8  6  3  
  8. 2  6  1  7  4  8  3  5  
  9. 2  6  8  3  1  4  7  5  
  10. 2  7  3  6  8  5  1  4  
  11. 2  7  5  8  1  4  6  3  
  12. 2  8  6  1  3  5  7  4  
  13. 3  1  7  5  8  2  4  6  
  14. 3  5  2  8  1  7  4  6  
  15. 3  5  2  8  6  4  7  1  
  16. 3  5  7  1  4  2  8  6  
  17. 3  5  8  4  1  7  2  6  
  18. 3  6  2  5  8  1  7  4  
  19. 3  6  2  7  1  4  8  5  
  20. 3  6  2  7  5  1  8  4  
  21. 3  6  4  1  8  5  7  2  
  22. 3  6  4  2  8  5  7  1  
  23. 3  6  8  1  4  7  5  2  
  24. 3  6  8  1  5  7  2  4  
  25. 3  6  8  2  4  1  7  5  
  26. 3  7  2  8  5  1  4  6  
  27. 3  7  2  8  6  4  1  5  
  28. 3  8  4  7  1  6  2  5  
  29. 4  1  5  8  2  7  3  6  
  30. 4  1  5  8  6  3  7  2  
  31. 4  2  5  8  6  1  3  7  
  32. 4  2  7  3  6  8  1  5  
  33. 4  2  7  3  6  8  5  1  
  34. 4  2  7  5  1  8  6  3  
  35. 4  2  8  5  7  1  3  6  
  36. 4  2  8  6  1  3  5  7  
  37. 4  6  1  5  2  8  3  7  
  38. 4  6  8  2  7  1  3  5  
  39. 4  6  8  3  1  7  5  2  
  40. 4  7  1  8  5  2  6  3  
  41. 4  7  3  8  2  5  1  6  
  42. 4  7  5  2  6  1  3  8  
  43. 4  7  5  3  1  6  8  2  
  44. 4  8  1  3  6  2  7  5  
  45. 4  8  1  5  7  2  6  3  
  46. 4  8  5  3  1  7  2  6  
  47. 5  1  4  6  8  2  7  3  
  48. 5  1  8  4  2  7  3  6  
  49. 5  1  8  6  3  7  2  4  
  50. 5  2  4  6  8  3  1  7  
  51. 5  2  4  7  3  8  6  1  
  52. 5  2  6  1  7  4  8  3  
  53. 5  2  8  1  4  7  3  6  
  54. 5  3  1  6  8  2  4  7  
  55. 5  3  1  7  2  8  6  4  
  56. 5  3  8  4  7  1  6  2  
  57. 5  7  1  3  8  6  4  2  
  58. 5  7  1  4  2  8  6  3  
  59. 5  7  2  4  8  1  3  6  
  60. 5  7  2  6  3  1  4  8  
  61. 5  7  2  6  3  1  8  4  
  62. 5  7  4  1  3  8  6  2  
  63. 5  8  4  1  3  6  2  7  
  64. 5  8  4  1  7  2  6  3  
  65. 6  1  5  2  8  3  7  4  
  66. 6  2  7  1  3  5  8  4  
  67. 6  2  7  1  4  8  5  3  
  68. 6  3  1  7  5  8  2  4  
  69. 6  3  1  8  4  2  7  5  
  70. 6  3  1  8  5  2  4  7  
  71. 6  3  5  7  1  4  2  8  
  72. 6  3  5  8  1  4  2  7  
  73. 6  3  7  2  4  8  1  5  
  74. 6  3  7  2  8  5  1  4  
  75. 6  3  7  4  1  8  2  5  
  76. 6  4  1  5  8  2  7  3  
  77. 6  4  2  8  5  7  1  3  
  78. 6  4  7  1  3  5  2  8  
  79. 6  4  7  1  8  2  5  3  
  80. 6  8  2  4  1  7  5  3  
  81. 7  1  3  8  6  4  2  5  
  82. 7  2  4  1  8  5  3  6  
  83. 7  2  6  3  1  4  8  5  
  84. 7  3  1  6  8  5  2  4  
  85. 7  3  8  2  5  1  6  4  
  86. 7  4  2  5  8  1  3  6  
  87. 7  4  2  8  6  1  3  5  
  88. 7  5  3  1  6  8  2  4  
  89. 8  2  4  1  7  5  3  6  
  90. 8  2  5  3  1  7  4  6  
  91. 8  3  1  6  2  5  7  4  
  92. 8  4  1  3  6  2  7  5  

上面一共输出的是92个结果。
0 0