【数据结构算法】递归:八皇后问题

野性酷女 2022-05-21 03:18 314阅读 0赞

八皇后

八皇后问题就是说如下图所示的国际象棋的棋盘中,放入8个皇后,所谓皇后就是国际象棋中的一个角色,它的功能就是能够打掉与它同一行同一列同一斜排的棋子,并且打击距离是整个棋盘。我们的任务就是在棋盘中挑选8个位置放上皇后,使得这八个皇后能够在棋盘中和平共处,不会被对方打掉。

解题思路

利用递归的手段解决,我们的主要思路是以行为单位遍历整个棋盘,每次遍历到一个位置判断一次当前位置是否危险(其同一行同一列两个斜线上是否有棋子)。若不危险则继续遍历下一行,当行==8的时候输出当前情况(也就是递归的终止条件)。若行!=8的时候那么就遍历下一行,也就是行加一,所以八皇后问题可以用递归来解决。

代码

  1. #include <stdio.h>
  2. int count = 0;//全局变量
  3. int notdanger(int row,int j,int (*chess)[8])
  4. {
  5. int i, flag1 =0, flag2 =0;
  6. //判断列方向
  7. for(i=0;i<8;i++)
  8. {
  9. if(*(*(chess+i)+j) != 0)
  10. {
  11. flag1 = 1;
  12. break;
  13. }
  14. }
  15. //判断左上方
  16. for(i = row,k=j;i>=0 && k>=0;i--,k--)
  17. {
  18. if(*(*(chess+i)+k) != 0)
  19. {
  20. flag2 = 1;
  21. break;
  22. }
  23. }
  24. //判断左下方
  25. for(i = row,k=j;i<0 && k>=0;i++,k--)
  26. {
  27. if(*(*(chess+i)+k) != 0)
  28. {
  29. flag3 = 1;
  30. break;
  31. }
  32. }
  33. //判断右上方
  34. for(i = row,k=j;i>=0 && k<0;i--,k++)
  35. {
  36. if(*(*(chess+i)+k) != 0)
  37. {
  38. flag4 = 1;
  39. break;
  40. }
  41. }
  42. //判断右下方
  43. for(i = row,k=j;i<0 && k<0;i++,k++)
  44. {
  45. if(*(*(chess+i)+k) != 0)
  46. {
  47. flag5 = 1;
  48. break;
  49. }
  50. }
  51. if(flag1 || flag2 || flag3 || flag4 || flag5)
  52. {
  53. return 0;
  54. }
  55. else
  56. {
  57. return 1;
  58. }
  59. }
  60. //row表示起始行
  61. //n表示列数
  62. //(*chess)[8]:表示指向棋盘每一行的指针
  63. void EightQueue(int row, int n, int (*chess)[8])
  64. {
  65. int chess2[8][8], i, j;//用来存放递归过程中的棋盘
  66. //将棋盘赋值给中间矩阵
  67. for(i = 0;i<8;i++)
  68. {
  69. for(j = 0;j<8;j++)
  70. {
  71. chess2[i][j] = chess[i][j];
  72. }
  73. }
  74. if (8 == row)
  75. {
  76. //输出当前这个矩阵
  77. for(i=0;i<8;i++)
  78. {
  79. for(j=0;j<8;j++)
  80. {
  81. //*(*(chess2+i)+j)利用指针操纵二维数组的一种方式
  82. printf("%d ",*(*(chess2+i)+j));
  83. }
  84. //每个矩阵的行与行之间空出一格来
  85. printf("\n");
  86. }
  87. //每一个可行方案之间空出一格来
  88. printf("\n");
  89. }
  90. //如果递归过程中没有满足终止条件
  91. else
  92. {
  93. //对于每一行(当前行数为n)来说,一共有八个位置,我需要判断每个位置是否危险,一旦确定当前位置不危险,就要将当前行的这一列的这个值赋值为1,并且进入下一行,执行一样的操作(这就是递归的精髓)。
  94. for(j = 0;j<n;i++)
  95. {
  96. if(notdanger(row,j,chees))
  97. {
  98. //将当前row行,j列这个值赋值为1
  99. for(i = 0;i<8;i++)
  100. {
  101. *((*chess+i)+j) = 0;
  102. }
  103. *((*chess+row)+j) = 1;
  104. EightQueen(row+1,n,chess);
  105. }
  106. }
  107. }
  108. }
  109. int main()
  110. {
  111. int chess[8][8],i,j;
  112. for(i = 0;i<8;i++)
  113. {
  114. for(j = 0;j<8;j++)
  115. {
  116. chess[i][j] = 0;
  117. }
  118. }
  119. EightQueen(8,8,chess);
  120. printf("总共有%d种解决方法\n",count);
  121. return 0;
  122. }

发表评论

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

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

相关阅读

    相关 --皇后

      八皇后这个典的问题,是每个真正程序员必须经历过的。这也是我第二次来解决这个问题了,第一次应该是学数据结构那时候吧。这次写起来顺利多了,基本没遇到什么卡壳的地方。递归+回溯。