有趣的数据结构算法12——利用递归解决八皇后问题

迷南。 2021-11-22 09:14 424阅读 0赞

有趣的数据结构算法12——利用递归解决八皇后问题

  • 题目复述
  • 解题思路
  • 实现代码
  • GITHUB下载连接

本次教程主要讲述如何利用递归解决八皇后问题,它和汉诺塔一样让人很难过。
在这里插入图片描述

题目复述

据说西洋棋手都具有一些比较神奇的技能,上厕所的时候还喜欢想怎么下棋,终于有一天,在刺激气体的刺激下,八皇后问题横空出世。
这是一个古老而著名的问题,在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问国际象棋上一共有多少个皇后。
在这里插入图片描述
其实是问有多少种摆法。

解题思路

解题时需要对每一行进行遍历。
接下来以例子来说明。
首先遍历第一行,按照任意两个皇后都不能处于同一行、同一列或同一斜线上的规则找到可以放下的点,此时找到第一列,放下棋子。
示例1
此时递归调用函数:

  1. EightQueen(row + 1, chess2)

再次遍历第二行,按照规则找到可以放下的点,此时找到第三列,放下棋子。
示例2
再次遍历第三行,按照规则找到可以放下的点,此时找到第五列,放下棋子。
示例3
再次遍历第四行,按照规则找到可以放下的点,此时找到第七列,放下棋子。
示例4
以此类推,继续遍历,直至第一行的八列全都成功遍历。该部分的核心代码为:

  1. for (j = 0; j < 8; j++){
  2. //遍历每一行的八列
  3. if (noDanger(row, j, chess2)) //判断是否有危险,没有危险则进行下一步
  4. {
  5. for (i = 0; i < 8; i++) //清除当前行,上一次循环留下的影响,如j=0对j=1的影响。
  6. chess2[row][i] = 0;
  7. chess2[row][j] = 1; //该位置安全,放下一个皇后
  8. EightQueen(row + 1, chess2); //查询下一行情况
  9. }
  10. }

如果有一次成功遍历完成八行,则代表每一行都放下了一个皇后,此时便解决了八皇后问题。
我们利用函数:

  1. if (8 == row){
  2. //如果到达row = 8 则代表第八行的棋盘都已经放上皇后,则所有行都放上了皇后。打印棋盘出来
  3. printf("第%d种:\n", ++count);
  4. for (i = 0; i < 8; i++){
  5. for (j = 0; j < 8; j++){
  6. printf("%d ", chess2[i][j]);
  7. }
  8. printf("\n");
  9. }
  10. printf("\n");
  11. }

将棋盘打印下来。

实现代码

  1. #include<stdio.h>
  2. int count = 0;
  3. int noDanger(int row, int col, int (*chess)[8]){
  4. int i,j,flag1 = 0,flag2 = 0,flag3 = 0,flag4 = 0,flag5=0;
  5. for (i = 0; i < 8; i++){
  6. //判断该列是否有其它皇后
  7. if (chess[i][col] != 0){
  8. flag1 = 1;
  9. break;
  10. }
  11. }
  12. for (i = row, j = col; i >= 0 && j >= 0; i--,j--){
  13. //判断左上角是否有其它皇后
  14. if (chess[i][j] != 0){
  15. flag2 = 1;
  16. break;
  17. }
  18. }
  19. for (i = row, j = col; i < 8 && j < 8; i++, j++){
  20. //判断右下角是否有其它皇后
  21. if (chess[i][j] != 0){
  22. flag3 = 1;
  23. break;
  24. }
  25. }
  26. for (i = row, j = col; i >= 0 && j < 8; i--, j++){
  27. //判断左下角是否有其它皇后
  28. if (chess[i][j] != 0){
  29. flag4 = 1;
  30. break;
  31. }
  32. }
  33. for (i = row, j = col; i < 8 && j >= 0; i++, j--){
  34. //判断右上角是否有其它皇后
  35. if (chess[i][j] != 0){
  36. flag5 = 1;
  37. break;
  38. }
  39. }
  40. if (flag1 || flag2 || flag3 || flag4 || flag5){
  41. //如果有其它皇后则不满足条件。return 0;
  42. return 0;
  43. }
  44. else{
  45. return 1;
  46. }
  47. }
  48. void EightQueen(int row,int chess[][8]){
  49. int chess2[8][8],i,j;
  50. for (i = 0; i < 8; i++){
  51. //将所有chess赋予局部棋盘chess2,这样可以不改变原chess的值
  52. for (j = 0; j < 8; j++){
  53. chess2[i][j] = chess[i][j];
  54. }
  55. }
  56. if (8 == row){
  57. //如果到达row = 8 则代表第八行的棋盘都已经放上皇后,则所有行都放上了皇后。打印棋盘出来
  58. printf("第%d种:\n", ++count);
  59. for (i = 0; i < 8; i++){
  60. for (j = 0; j < 8; j++){
  61. printf("%d ", chess2[i][j]);
  62. }
  63. printf("\n");
  64. }
  65. printf("\n");
  66. }
  67. else{
  68. for (j = 0; j < 8; j++){
  69. if (noDanger(row, j, chess2)) //判断是否有危险,没有危险则进行下一步
  70. {
  71. for (i = 0; i < 8; i++) //清除当前行,上一次循环留下的影响,如j=0对j=1的影响。
  72. chess2[row][i] = 0;
  73. chess2[row][j] = 1; //该位置安全,放下一个皇后
  74. EightQueen(row + 1, chess2); //查询下一行情况
  75. }
  76. }
  77. }
  78. }
  79. void main(){
  80. int chess[8][8], i, j;
  81. for (i = 0; i < 8; i++){
  82. for (j = 0; j < 8; j++){
  83. chess[i][j] = 0; //赋予棋盘初值,全是0;
  84. }
  85. }
  86. EightQueen(0,chess);
  87. }

GITHUB下载连接

https://github.com/bubbliiiing/Data-Structure-and-Algorithm

希望得到朋友们的喜欢。
有问题的朋友可以提问噢。

发表评论

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

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

相关阅读

    相关 解决皇后回溯算法

    问题简述:八皇后问题是一个古来而著名的问题,该问题是19世纪著名的数学家高斯同学提出来的。在8\8的国际象棋上摆放八个皇后,使其不能互相的攻击,也就是说,任意的两个皇后不能放在