递归算法计算八皇后问题(Eight Queen Problem with Recursive Algorithm)

小灰灰 2022-06-15 01:40 196阅读 0赞

1.概念

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

Center

2.实现

  1. #include <stdio.h>
  2. int count = 0;
  3. int notDanger(int row, int j, int(*chess)[8]); //判断当前点是否 不在危险位置
  4. void EightQueen(int row, int n, int(*chess)[8]); //递归计算所有皇后位置
  5. int main()
  6. {
  7. int chess[8][8], i, j;
  8. //初始化为全0
  9. for (i = 0; i < 8; i++)
  10. {
  11. for (j = 0; j < 8; j++)
  12. {
  13. chess[i][j] = 0;
  14. }
  15. }
  16. EightQueen(0, 8, chess);
  17. printf("总共有 %d 种解决方法!\n",count); //每一种可能分割线
  18. return 0;
  19. }
  20. int notDanger(int row, int j, int(*chess)[8])
  21. {
  22. int i, k;
  23. int flag1 = 0, flag2 = 0, flag3 = 0, flag4 = 0, flag5 = 0; //是否 有皇后
  24. //判断列(正上正下)方向
  25. for (i = 0; i < 8; i++)
  26. {
  27. if (*(*(chess + i) + j) != 0)
  28. {
  29. flag1 = 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. flag2 = 1;
  39. break;
  40. }
  41. }
  42. //判断左下方
  43. for (i = row, k = j; i < 8 && k >= 0; i++, k--)
  44. {
  45. if (*(*(chess + i) + k) != 0)
  46. {
  47. flag3 = 1;
  48. break;
  49. }
  50. }
  51. //判断右上方
  52. for (i = row, k = j; i >= 0 && k < 8; i--, k++)
  53. {
  54. if (*(*(chess + i) + k) != 0)
  55. {
  56. flag4 = 1;
  57. break;
  58. }
  59. }
  60. //判断右下方
  61. for (i = row, k = j; i < 8 && k < 8; i++, k++)
  62. {
  63. if (*(*(chess + i) + k) != 0)
  64. {
  65. flag5 = 1;
  66. break;
  67. }
  68. }
  69. //若有一个方向有皇后,就是危险的,返回0,否则安全返回1
  70. if (flag1 || flag2 || flag3 || flag4 || flag5)
  71. {
  72. return 0;
  73. }
  74. else
  75. {
  76. return 1;
  77. }
  78. }
  79. //参数row:起始行
  80. //参数n:列数
  81. //参数(*chess)[8]:表示指向棋盘每一行的指针
  82. void EightQueen(int row, int n, int(*chess)[8])
  83. {
  84. int chess2[8][8]; //存放待输出棋盘格
  85. int i, j;
  86. for (i = 0; i < 8; i++)
  87. {
  88. for (j = 0; j < 8; j++)
  89. {
  90. chess2[i][j] = chess[i][j];
  91. }
  92. }
  93. //终止条件
  94. if (8 == row)
  95. {
  96. printf("第 %d 种:\n", count + 1);
  97. for (i = 0; i < 8; i++) //行
  98. {
  99. for (j = 0; j < 8; j++) //列
  100. {
  101. printf("%d ", *(*(chess2 + i) + j)); //输出第i行第j列元素
  102. }
  103. printf("\n");
  104. }
  105. count++;
  106. printf("——————————————\n"); //每一种可能分割线
  107. }
  108. else
  109. {
  110. for (j = 0; j < n; j++) //从上到下逐列选择皇后位置
  111. {
  112. if (notDanger(row, j, chess)) //判断是否 不在危险位置(不在对应点直线斜线上)
  113. {
  114. for (i = 0; i < 8; i++) //每row行中8个元素均初始化为0
  115. {
  116. *(*(chess2 + row) + i) = 0;
  117. }
  118. *(*(chess2 + row) + j) = 1; //row行 notDanger列j 确定为皇后位置******
  119. EightQueen(row + 1, n, chess2); //递归计算下一行
  120. }
  121. }
  122. }
  123. }

3.结果

……..

Center 1

发表评论

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

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

相关阅读

    相关 --皇后

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