我正试图在4x4板上用java中的回溯和递归来解决Knights巡演问题,并且在输出中我得到了这一步序列:
1 13 16 15
10 7 4 14
5 2 11 8
12 9 6 3
在右上角,14,15和16彼此相邻,这是不可能的,因为骑士在棋盘上移动成L形。如果有人能帮我解决这个问题,我将感激不尽。
代码:
public class KnightsTour {
private static int board[][] = new int[4][4];
private static int stepCounter = 1;
public Test() {
initBoard(board);
tour(0,0);
printSol(board);
}
public static void printSol(int[][] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if(a[i][j]>9){
System.out.print(a[i][j] + " ");
}else{
System.out.print(a[i][j] + " ");
}
}
System.out.println();
}
System.out.println();
}
public static void initBoard(int[][] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = -1;
}
}
}
public void tour(int x, int y) {
if (((x < 0) || (x >= 4) || (y < 0) || (y >= 4)) || (board[x][y] != -1)) {
return;
}else{
board[x][y] = stepCounter++;
tour(x+2, y+1);
tour(x+1, y-2);
tour(x+1, y+2);
tour(x-1, y+2);
tour(x-2, y-1);
tour(x-2, y+1);
tour(x-1, y-2);
tour(x+2, y-1);
}
}
public static void main(String[] args){
new KnightsTour();
}
}
答案 0 :(得分:1)
您需要使函数返回一个布尔值,以便它可以告诉调用函数它是否成功。否则,只要你已经尝试了所有可能的组合,即使你已经找到解决方案,你也会继续。
然后,在每次调用函数时,您需要检查返回值,如果成功则返回true。
然后你显然需要在完成时返回true。
我建议像:
if (stepCounter == 1 + board.length * board[0].length)
return true;
在board[x][y] = stepCounter++;
之后。
您需要还原在函数调用结束时所做的任何更改,即stepCounter
需要减少,board[x][y]
需要设置为-1
。
成功完成这些更改之后,您应该看到所有-1
的结果,因为在4x4电路板上不可能,但将其更改为8x8应该会成功。
请注意,我之前没有使用17
- 最好不要使用硬编码值(例如,x >= 4
)。请使用数组的大小或final
值。
答案 1 :(得分:0)
您的tour()函数似乎将广场的值设置为首次访问的订单的步数计数器。但是你正在尝试多种选择。当你到达12时,你的第一个旅行死亡结束 - 随后的一次尝试触及13-16个方格中的每一个。
您需要存储当前游览的状态,而不是您访问的顺序。例如。如果你回溯,当前的广场不再是巡演的一部分。如果你找到一个旅游,你应该停下来,因为你已经完成了。