当前位置:   article > 正文

[C++实现]八皇后问题_八皇后问题c++代码

八皇后问题c++代码

一、题意解析

国际象棋中的皇后,可以横向、纵向、斜向移动。如何在一个8X8的棋盘上放置8个皇后,使得任意两个皇后都不在同一条横线、竖线、斜线方向上?八皇后问题是一个古老的问题,于1848年由一位国际象棋棋手提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,如何求解?以高斯为代表的许多数学家先后研究过这个问题。后来,当计算机问世,通过计算机程序的运算可以轻松解出这个问题。 

二、如何解决八皇后问题?

        所谓递归回溯,本质上是一种枚举法。这种方法从棋盘的第一行开始尝试摆放第一个皇后,摆放成功后,递归一层,再遵循规则在棋盘第二行来摆放第二个皇后。如果当前位置无法摆放,则向右移动一格再次尝试,如果摆放成功,则继续递归一层,摆放第三个皇后......

  如果某一层看遍了所有格子,都无法成功摆放,则回溯到上一个皇后,让上一个皇后右移一格,再进行递归。如果八个皇后都摆放完毕且符合规则,那么就得到了其中一种正确的解法。说起来有些抽象,我们来看一看递归回溯的详细过程。

1.第一层递归,尝试在第一行摆放第一个皇后

 2.第二层递归,尝试在第二行摆放第二个皇后(前两格被第一个皇后封锁,只能落在第三格):

3.第三层递归,尝试在第三行摆放第三个皇后(前四格被第一第二个皇后封锁,只能落在第五格):

4.第四层递归,尝试在第四行摆放第四个皇后(第一格被第二个皇后封锁,只能落在第二格):

5.第五层递归,尝试在第五行摆放第五个皇后(前三格被前面的皇后封锁,只能落在第四格): 

 6.由于所有格子都“绿了”,第六行已经没办法摆放皇后,于是进行回溯,重新摆放第五个皇后第八格

7.第六行仍然没有办法摆放皇后,第五行也已经尝试遍了,于是回溯到第四行,重新摆放第四个皇后第七格: 

 8.继续摆放第五个皇后,以此类推......

 三、八皇后问题的代码实现

解决八皇后问题,可以分为两个层面:

1.找出第一种正确摆放方式,也就是深度优先遍历。

2.找出全部的正确摆放方式,也就是广度优先遍历。

 我们本篇只介绍如何找出第一种正确摆放方式。具体代码如下:

  1. //"八皇后问题回溯实现"
  2. #include <iostream>
  3. using namespace std;
  4. const int ArSize = 8;//这个数等于几,就是几皇后。
  5. int num = 0;
  6. void solve(bool arr[ArSize][ArSize], int row);
  7. bool check(bool arr[ArSize][ArSize], int row, int column);
  8. void outPut(bool arr[ArSize][ArSize]);
  9. int main()
  10. {
  11. bool chessboard[ArSize][ArSize];
  12. // 数组初始化
  13. for (auto &i : chessboard)
  14. {
  15. for (auto &j : i)
  16. {
  17. j = false;
  18. }
  19. }
  20. solve(chessboard, 0);
  21. cout << "八皇后问题共有" << num << "种解!" << endl;
  22. system("pause");
  23. return 0;
  24. }
  25. // 回溯法
  26. void solve(bool arr[ArSize][ArSize], int row)
  27. {
  28. for (int column = 0; column < ArSize; ++column)
  29. {
  30. arr[row][column] = true;
  31. if (check(arr, row, column))
  32. {
  33. if (row + 1 == ArSize)
  34. {
  35. outPut(arr);
  36. }
  37. else
  38. {
  39. solve(arr, row + 1);
  40. }
  41. }
  42. arr[row][column] = false;
  43. }
  44. }
  45. // 判断皇后的落点是否合规
  46. bool check(bool arr[ArSize][ArSize], int row, int column)
  47. {
  48. if (row == 0)
  49. {
  50. return true;
  51. }
  52. int i, j;
  53. // 判断纵向是否有冲突
  54. for (i = 0; i < row; ++i)
  55. {
  56. if (arr[i][column])
  57. {
  58. return false;
  59. }
  60. }
  61. i = row - 1;
  62. j = column - 1;
  63. // 判断正斜对角线是否有冲突
  64. while (i >= 0 && j >= 0)
  65. {
  66. if (arr[i][j])
  67. {
  68. return false;
  69. }
  70. --i;
  71. --j;
  72. }
  73. i = row - 1;
  74. j = column + 1;
  75. // 判断负斜对角线是否有冲突
  76. while (i >= 0 && j <= ArSize - 1)
  77. {
  78. if (arr[i][j])
  79. {
  80. return false;
  81. }
  82. --i;
  83. ++j;
  84. }
  85. return true;
  86. }
  87. // 打印每种正确的解法
  88. void outPut(bool arr[ArSize][ArSize])
  89. {
  90. ++num;
  91. cout << "**********************" << num << "*********************" << endl;
  92. for (int i = 0; i < ArSize; ++i)
  93. {
  94. for (int j = 0; j < ArSize; ++j)
  95. {
  96. cout << arr[i][j] << " ";
  97. }
  98. cout << endl;
  99. }
  100. cout << "*********************************************" << endl;
  101. }

输出结果的部分截图如下:

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

闽ICP备14008679号