马踏棋盘(关于回溯法的应用)

问题描述:

在中国象棋中,棋子马的走法是走“日”字型;

现有一8*8的中国象棋棋盘,棋子马从任意给定一点出发,走“日”字型,要求为马

寻找一条走遍棋盘每一格并且只经过一次的一条路径。






给定一个初始的坐标,如(0,0),从该点向外走“日”字型,有两种走法,若起始点

在(4,4),棋子的每个方向都可以走,有八种走法。

所以正常计算的计算量过大,使用回溯法会优化不少

回溯算法的基本思想是:

        回溯在迷宫搜索中使用很常见,就是这条路走不通,然后返回前一个路口,继续

下一条路。八皇后问题就是回溯算法的典型,第一步按照顺序放一个皇后,然后第二

步符合要求放第2个皇后,如果没有位置符合要求,那么就要改变第一个皇后的位

置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了。回溯算法说白了

就是穷举法。不过回溯算法使用剪枝函数,剪去一些不可能到达 最终状态(即答案状

态)的节点,从而减少状态空间树节点的生成。



  1. #include <stdio.h>
  2. #include <conio.h>
  3. #define N 8


  4. struct nx//实时移动到的位置坐标
  5. {
  6. int m;
  7. int n;
  8. };


  9. int array[9][9];
  10. int count;//生成结果数


  11. void Initialization()//初始化函数
  12. {
  13. int line;
  14. int row;


  15. for (line = 1; line <= 8; line++)
  16. {
  17. for (row = 1; row <= 8; row++)
  18. {
  19. array[line][row] = 0;//先对行列都赋值为0,表示没有走过
  20.   //每当马走过一个点,赋值为1
  21. }
  22. }
  23. }


  24. struct nx move_house(int direct, int x, int y) //马从位置(x,y)出发,从各个方向开始尝试
  25. {
  26. struct nx next;
  27. switch (direct)
  28. {
  29. case 0: next.m = x + 1; next.n = y + 2; break;
  30. case 1: next.m = x + 2; next.n = y + 1; break;
  31. case 2: next.m = x + 2; next.n = y - 1; break;
  32. case 3: next.m = x + 1; next.n = y - 2; break;
  33. case 4: next.m = x - 1; next.n = y - 2; break;
  34. case 5: next.m = x - 2; next.n = y - 1; break;
  35. case 6: next.m = x - 2; next.n = y + 1; break;
  36. case 7: next.m = x - 1; next.n = y + 2; break;
  37. }
  38. return next;//将位置坐标的及结构体返回
  39. }


  40. int Illegal_put(int deepth, int m, int n)
  41. {
  42. if (n > N || m > N || n < 1 || m < 1 || array[m][n] != 0)
  43. return 0;//当棋子超出棋盘范围时候,或该点已经走过,对这个位置赋值0
  44. else
  45. return 1;
  46. }


  47. void List_output()
  48. {
  49. int line;
  50. int row;
  51. printf("第[%d]种走法\n", count+1);
  52. for (line = 1; line <= N; line++)
  53. {
  54. for (row = 1; row <= N; row++)
  55. {
  56. printf("%3d", array[line][row]);
  57. }
  58. printf("\n");
  59. }
  60. printf("\n");
  61. }


  62. void house_track(int deepth, int x,int y)
  63. {
  64. int direct;
  65. struct nx next;
  66. if (deepth <= N*N)
  67. {
  68. for (direct = 0; direct <= 7; direct++)
  69. {
  70. next = move_house(direct, x, y);
  71. if (Illegal_put(deepth, next.m, next.n))
  72. {
  73. array[next.m][next.n] = deepth;
  74. house_track(deepth + 1, next.m, next.n);
  75. }
  76. }
  77. if (direct == 8)
  78. array[x][y] = 0;
  79. }
  80. else
  81. {
  82. List_output();
  83. array[x][y] = 0;
  84. count++;
  85. }
  86. }



  87. int main()
  88. {
  89. int start_x;
  90. int start_y;//棋子开始的坐标
  91. Initialization();//对棋盘初始化
  92. printf("输出棋子马的初始坐标(x,y):");
  93. scanf("%d%d", &start_x, &start_y);
  94. array[start_x][start_y] = 1;
  95. count = 0;
  96. house_track(2, start_x, start_y);
  97. _getch();
  98. printf("一共有%d种可能\n", count);
  99. }









猜你喜欢

转载自blog.csdn.net/nightvales/article/details/80558240
今日推荐