迷宫中有一个球,它有空地 (表示为 0
) 和墙 (表示为 1
)。球可以向上、向下、向左或向右滚过空地,但直到撞上墙之前它都不会停止滚动。当球停止时,它才可以选择下一个滚动方向。
给定 m × n
的迷宫(maze
),球的起始位置 (start = [startrow, startcol]
) 和目的地 (destination = [destinationrow, destinationcol]
),返回球在目的地 (destination
) 停止的最短距离。如果球不能在目的地 (destination
) 停止,返回 -1
。
距离是指球从起始位置 ( 不包括 ) 到终点 ( 包括 ) 所经过的空地数。
你可以假设迷宫的边界都是墙 ( 见例子 )。
示例 1:
输入: maze = [[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]], start = [0,4], destination = [4,4] 输出: 12 解析: 一条最短路径 : left -> down -> left -> down -> right -> down -> right。 总距离为 1 + 1 + 3 + 1 + 2 + 2 + 2 = 12。
示例 2:
输入: maze = [[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]], start = [0,4], destination = [3,2] 输出: -1 解析: 球不可能在目的地停下来。注意,你可以经过目的地,但不能在那里停下来。
示例 3:
输入: maze = [[0,0,0,0,0],[1,1,0,0,1],[0,0,0,0,0],[0,1,0,0,1],[0,1,0,0,0]], start = [4,3], destination = [0,1] 输出: -1
注意:
m == maze.length
n == maze[i].length
1 <= m, n <= 100
maze[i][j]
是0
或1
.start.length == 2
destination.length == 2
0 <= startrow, destinationrow < m
0 <= startcol, destinationcol < n
- 球和目的地都存在于一个空地中,它们最初不会处于相同的位置。
-
迷宫至少包含两个空地。
BFS。
注意在一般的广度优先搜索中,我们不会经过同一个节点超过一次,但在这道题目中,只要从起始位置到当前节点的步数 step 小于之前记录的最小步数 dist[i, j]
,我们就会把 (i, j)
再次加入队列中。
class Solution:
def shortestDistance(
self, maze: List[List[int]], start: List[int], destination: List[int]
) -> int:
m, n = len(maze), len(maze[0])
rs, cs = start
rd, cd = destination
dist = [[inf] * n for _ in range(m)]
dist[rs][cs] = 0
q = deque([(rs, cs)])
while q:
i, j = q.popleft()
for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]:
x, y, step = i, j, dist[i][j]
while 0 <= x + a < m and 0 <= y + b < n and maze[x + a][y + b] == 0:
x, y, step = x + a, y + b, step + 1
if step < dist[x][y]:
dist[x][y] = step
q.append((x, y))
return -1 if dist[rd][cd] == inf else dist[rd][cd]
class Solution {
public int shortestDistance(int[][] maze, int[] start, int[] destination) {
int m = maze.length;
int n = maze[0].length;
int[][] dist = new int[m][n];
for (int i = 0; i < m; ++i) {
Arrays.fill(dist[i], Integer.MAX_VALUE);
}
dist[start[0]][start[1]] = 0;
Deque<int[]> q = new LinkedList<>();
q.offer(start);
int[] dirs = {-1, 0, 1, 0, -1};
while (!q.isEmpty()) {
int[] p = q.poll();
int i = p[0], j = p[1];
for (int k = 0; k < 4; ++k) {
int x = i, y = j, step = dist[i][j];
int a = dirs[k], b = dirs[k + 1];
while (
x + a >= 0 && x + a < m && y + b >= 0 && y + b < n && maze[x + a][y + b] == 0) {
x += a;
y += b;
++step;
}
if (step < dist[x][y]) {
dist[x][y] = step;
q.offer(new int[] {x, y});
}
}
}
return dist[destination[0]][destination[1]] == Integer.MAX_VALUE
? -1
: dist[destination[0]][destination[1]];
}
}
class Solution {
public:
int shortestDistance(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
int m = maze.size();
int n = maze[0].size();
vector<vector<int>> dist(m, vector<int>(n, INT_MAX));
dist[start[0]][start[1]] = 0;
queue<vector<int>> q{{start}};
vector<int> dirs = {-1, 0, 1, 0, -1};
while (!q.empty()) {
auto p = q.front();
q.pop();
int i = p[0], j = p[1];
for (int k = 0; k < 4; ++k) {
int x = i, y = j, step = dist[i][j];
int a = dirs[k], b = dirs[k + 1];
while (x + a >= 0 && x + a < m && y + b >= 0 && y + b < n && maze[x + a][y + b] == 0) {
x += a;
y += b;
++step;
}
if (step < dist[x][y]) {
dist[x][y] = step;
q.push({x, y});
}
}
}
return dist[destination[0]][destination[1]] == INT_MAX ? -1 : dist[destination[0]][destination[1]];
}
};
func shortestDistance(maze [][]int, start []int, destination []int) int {
m, n := len(maze), len(maze[0])
dist := make([][]int, m)
for i := range dist {
dist[i] = make([]int, n)
for j := range dist[i] {
dist[i][j] = math.MaxInt32
}
}
dist[start[0]][start[1]] = 0
q := [][]int{start}
dirs := []int{-1, 0, 1, 0, -1}
for len(q) > 0 {
i, j := q[0][0], q[0][1]
q = q[1:]
for k := 0; k < 4; k++ {
x, y, step := i, j, dist[i][j]
a, b := dirs[k], dirs[k+1]
for x+a >= 0 && x+a < m && y+b >= 0 && y+b < n && maze[x+a][y+b] == 0 {
x, y, step = x+a, y+b, step+1
}
if step < dist[x][y] {
dist[x][y] = step
q = append(q, []int{x, y})
}
}
}
if dist[destination[0]][destination[1]] == math.MaxInt32 {
return -1
}
return dist[destination[0]][destination[1]]
}