题目
对于一个10*10的迷宫,入口在第一行第二列,出口在最后一行第九列。迷宫中“#”代表墙,“.”代表通路,从任意一个“.”点只能一步走到上下左右四个方向的“.”点。求出走出迷宫所需要的最少步数。
- 测试输入
#.########
#........#
#........#
#........#
#........#
#........#
#........#
#........#
#........#
########.#
- 测试输出
16
分析
对图进行广度优先搜索就可以找出所有可行的路径,且最先找到的路径就是最短路径。关键是如何在广度优先搜索过程中记录所需要的步数,这里可以使用Pos
这个数据结构,其中包含x
,y
和layer
三个成员,其中layer
表示当前位置在搜索过程中所在的层,亦即所走的步数。每搜索到一个位置后,对其后续可行位置的层增1,接着对后续位置继续搜索。还要注意对所有已经搜索过的点进行标记,保证搜索方向是前向进行的。
代码
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
public class Maze{
static final int N = 10;
static final int[][] MOVES = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
// 位置类
static class Pos {
int x;
int y;
int layer;// 当前位置在搜索中所处的层
Pos(int x, int y, int layer) {
this.x = x;
this.y = y;
this.layer = layer;
}
@Override
public boolean equals(Object obj) {
return ((Pos) obj).x == this.x && ((Pos) obj).y == this.y;
}
}
static int solution(char[][] maze) {
Queue<Pos> queue = new ArrayDeque<>(N * N);
Pos start = new Pos(0, 1, 0);
Pos end = new Pos(N - 1, N - 2, 0);
queue.add(start);
Pos curPos;
while (!queue.isEmpty()) {
curPos = queue.remove();
if (curPos.equals(end)) {// 找到的第一条路径一定是最短路径
return curPos.layer;
}
maze[curPos.x][curPos.y] = 'o';// 标记已经访问过的点,保证前向搜索
for (int[] step : MOVES) {
int x = curPos.x + step[0];
int y = curPos.y + step[1];
if (x >= 0 && x < N && y >= 0 && y < N && maze[x][y] == '.') {
int layer = curPos.layer + 1;
Pos nextPos = new Pos(x, y, layer);
queue.add(nextPos);
}
}
}
return -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[][] maze = new char[N][N];
for (int i = 0; i < N; i++) {
maze[i] = sc.nextLine().toCharArray();
}
System.out.println(solution(maze));
}
}