Java DFS+贪心解决骑士游历问题
题目
骑士游历
骑士游历问题是指,在国际象棋的棋盘(8行*8列)上,一个马要遍历棋盘,即走到棋盘上的每一格,并且每隔只到达一次。设码在棋盘的某一位置(x,y)上,按照“走马日”的规则,下一步有8个方向走,如图所示。若给定起始位置(x0,y0),使用站和队列探索出一条马遍历棋盘的路径。
8 1 7 2 马 6 3 5 4
回溯枚举解法
这道题的解法思路和走迷宫类似。
首先是新建一个8个方向移动的结点类:
1 |
|
我们这里用一个数组保存每个点搜索过的方向,如果这个点搜索过北偏东方向的话,就标为1。回溯之后可以根据这个信息搜索其他方向。
和走迷宫稍有不同的是,一个点可由多个方向抵达,并且抵达后的棋盘状况不一定。所以回溯的时候,要把沿途的点的状态清为0。
当栈的size等于64的时候,就代表所有点都走过且仅走过一遍了。再倒着把每个点的路径标上、输出就ok了。
思路上是这样的,但实际运行的时候发现,8*8的棋盘dfs时间异常长,是得不出结果的。这个做法只能用于较小的棋盘。
最后栈所保存的元素就是路径上的每一个点了。
优化前代码如下:
1 | public static int chess[][]=new int[9][9]; |
使用贪心(预见算法)优化
贪心优化的思路是:有选择性的走下一个点,先走最难到达的点。
所以我们这里增加了一个新方法 public static int countAccess(Point p) 来计算8个方向中有多少个方向可以到达p点。
然后选择方向的时候以此为标准,先走去最难走的方向,就可以实现优化了。
代码如下:
1 | package lab3.Knight; |
代码以及运行结果
1 | System.out.println(KnightProblemSolve.solveByStackWithOpti(new Point(4,5))); |
所耗时间仅为20ms。
参考文章
Java DFS+贪心解决骑士游历问题