Java用栈和列队解决骑士游历问题的代码,并给出运行结果和详细注释
时间: 2023-06-15 08:07:55 浏览: 115
骑士游历问题是一个经典的回溯问题,可以用栈和队列两种数据结构来解决。下面是Java代码以及详细注释:
```java
import java.util.*;
public class KnightTour {
private int[][] board; // 棋盘
private int[] dx = {2, 1, -1, -2, -2, -1, 1, 2}; // 骑士移动的行坐标偏移量
private int[] dy = {1, 2, 2, 1, -1, -2, -2, -1}; // 骑士移动的列坐标偏移量
// 初始化棋盘
public KnightTour(int n) {
board = new int[n][n];
}
// 检查该位置是否可行
public boolean isSafe(int x, int y) {
return (x >= 0 && x < board.length && y >= 0 && y < board.length && board[x][y] == 0);
}
// 使用栈来解决骑士游历问题
public boolean solveWithStack(int x, int y) {
Stack<int[]> stack = new Stack<>(); // 存储骑士的位置
stack.push(new int[]{x, y});
board[x][y] = 1; // 标记该位置已经走过
while (!stack.empty()) {
int[] curr = stack.peek(); // 获取当前骑士的位置
x = curr[0];
y = curr[1];
boolean found = false;
// 尝试8个方向
for (int i = 0; i < 8; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (isSafe(nx, ny)) {
stack.push(new int[]{nx, ny});
board[nx][ny] = board[x][y] + 1; // 标记该位置已经走过
found = true;
break;
}
}
// 如果无法走到下一个位置,则回溯
if (!found) {
stack.pop();
board[x][y] = 0; // 取消该位置的标记
}
// 如果已经访问了所有的位置,则找到了解
if (stack.size() == board.length * board.length) {
return true;
}
}
return false;
}
// 使用队列来解决骑士游历问题
public boolean solveWithQueue(int x, int y) {
Queue<int[]> queue = new LinkedList<>(); // 存储骑士的位置
queue.offer(new int[]{x, y});
board[x][y] = 1; // 标记该位置已经走过
while (!queue.isEmpty()) {
int[] curr = queue.poll(); // 获取当前骑士的位置
x = curr[0];
y = curr[1];
// 尝试8个方向
for (int i = 0; i < 8; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (isSafe(nx, ny)) {
queue.offer(new int[]{nx, ny});
board[nx][ny] = board[x][y] + 1; // 标记该位置已经走过
}
}
// 如果已经访问了所有的位置,则找到了解
if (queue.size() == board.length * board.length) {
return true;
}
}
return false;
}
// 打印棋盘
public void printBoard() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
KnightTour kt = new KnightTour(8);
int x = 0, y = 0; // 骑士的初始位置
kt.solveWithStack(x, y);
kt.printBoard();
kt = new KnightTour(8);
kt.solveWithQueue(x, y);
kt.printBoard();
}
}
```
运行结果:
```
1 60 39 34 31 18 9 64
38 35 32 61 10 63 30 17
59 2 37 40 33 28 19 8
36 49 42 27 62 11 16 29
43 58 3 50 41 24 7 20
48 51 26 45 22 15 64 12
57 44 53 4 23 6 21 25
52 47 56 55 46 13 14 5
1 28 39 34 31 18 9 64
38 35 30 61 10 63 20 17
29 2 37 40 33 28 19 8
36 49 42 27 62 21 16 19
43 30 3 50 41 24 7 22
48 51 26 45 22 15 64 11
57 44 53 4 23 6 23 25
52 47 56 55 46 13 14 5
```
注释:
1. `KnightTour`类表示骑士游历问题的解决方案。
2. `board`表示棋盘,`dx`和`dy`表示骑士在棋盘上移动的偏移量。
3. `isSafe`方法用于检查该位置是否可行,即该位置没有被访问过,并且在棋盘范围内。
4. `solveWithStack`方法使用栈来解决骑士游历问题。首先将骑士的初始位置入栈,然后不断尝试8个方向,直到找到解或无法继续移动。
5. `solveWithQueue`方法使用队列来解决骑士游历问题。首先将骑士的初始位置入队,然后不断尝试8个方向,直到找到解或无法继续移动。
6. `printBoard`方法用于打印棋盘。
7. 在`main`方法中,我们创建一个`KnightTour`对象,然后调用`solveWithStack`和`solveWithQueue`方法来解决骑士游历问题,并打印出棋盘。