题目描述
给你一个 m x n
的二进制矩形 grid
和一个整数 health
表示你的健康值。
你开始于矩形的左上角 (0, 0)
,你的目标是矩形的右下角 (m - 1, n - 1)
。
你可以在矩形中往上下左右相邻格子移动,但前提是你的健康值始终是 正数 。
对于格子 (i, j)
,如果 grid[i][j] = 1
,那么这个格子视为 不安全 的,会使你的健康值减少 1 。
如果你可以到达最终的格子,请你返回 true
,否则返回 false
。
注意 ,当你在最终格子的时候,你的健康值也必须为 正数 。
示例 1:
输入:grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]], health = 1
输出:true
解释:
沿着下图中灰色格子走,可以安全到达最终的格子。
示例 2:
输入:grid = [[0,1,1,0,0,0],[1,0,1,0,0,0],[0,1,1,1,0,1],[0,0,1,0,1,0]], health = 3
输出:false
解释:
健康值最少为 4 才能安全到达最后的格子。
示例 3:
输入:grid = [[1,1,1],[1,0,1],[1,1,1]], health = 5
输出:true
解释:
沿着下图中灰色格子走,可以安全到达最终的格子。
任何不经过格子 (1, 1)
的路径都是不安全的,因为你的健康值到达最终格子时,都会小于等于 0 。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 50
2 <= m * n
1 <= health <= m + n
grid[i][j]
要么是 0 ,要么是 1 。
解法
方法一:BFS
我们定义一个二维数组 $\textit{dist}$,其中 $\textit{dist}[i][j]$ 表示从左上角到达 $(i, j)$ 位置的最小健康值。初始时,我们将 $\textit{dist}[0][0]$ 设为 $\textit{grid}[0][0]$,并将 $(0, 0)$ 加入队列 $\textit{q}$ 中。
随后我们不断取出队列中的元素 $(x, y)$,并尝试向四个方向移动。如果移动到了一个合法的位置 $(nx, ny)$,且从 $(x, y)$ 移动到 $(nx, ny)$ 的健康值消耗更小,那么我们就可以更新 $\textit{dist}[nx][ny] = \textit{dist}[x][y] + \textit{grid}[nx][ny]$,并将 $(nx, ny)$ 加入队列 $\textit{q}$ 中。
最终,当队列为空时,我们就可以得到 $\textit{dist}[m-1][n-1]$,即从左上角到达右下角的最小健康值。如果这个值小于 $\textit{health}$,那么我们就可以到达右下角,否则我们无法到达。
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩形的行数和列数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | class Solution:
def findSafeWalk(self, grid: List[List[int]], health: int) -> bool:
m, n = len(grid), len(grid[0])
dist = [[inf] * n for _ in range(m)]
dist[0][0] = grid[0][0]
q = deque([(0, 0)])
dirs = (-1, 0, 1, 0, -1)
while q:
x, y = q.popleft()
for a, b in pairwise(dirs):
nx, ny = x + a, y + b
if (
0 <= nx < m
and 0 <= ny < n
and dist[nx][ny] > dist[x][y] + grid[nx][ny]
):
dist[nx][ny] = dist[x][y] + grid[nx][ny]
q.append((nx, ny))
return dist[-1][-1] < health
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | class Solution {
public boolean findSafeWalk(List<List<Integer>> grid, int health) {
int m = grid.size();
int n = grid.get(0).size();
int[][] dist = new int[m][n];
for (int[] row : dist) {
Arrays.fill(row, Integer.MAX_VALUE);
}
dist[0][0] = grid.get(0).get(0);
Deque<int[]> q = new ArrayDeque<>();
q.offer(new int[] {0, 0});
final int[] dirs = {-1, 0, 1, 0, -1};
while (!q.isEmpty()) {
int[] curr = q.poll();
int x = curr[0], y = curr[1];
for (int i = 0; i < 4; i++) {
int nx = x + dirs[i];
int ny = y + dirs[i + 1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n
&& dist[nx][ny] > dist[x][y] + grid.get(nx).get(ny)) {
dist[nx][ny] = dist[x][y] + grid.get(nx).get(ny);
q.offer(new int[] {nx, ny});
}
}
}
return dist[m - 1][n - 1] < health;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | class Solution {
public:
bool findSafeWalk(vector<vector<int>>& grid, int health) {
int m = grid.size();
int n = grid[0].size();
vector<vector<int>> dist(m, vector<int>(n, INT_MAX));
dist[0][0] = grid[0][0];
queue<pair<int, int>> q;
q.emplace(0, 0);
int dirs[5] = {-1, 0, 1, 0, -1};
while (!q.empty()) {
auto [x, y] = q.front();
q.pop();
for (int i = 0; i < 4; ++i) {
int nx = x + dirs[i];
int ny = y + dirs[i + 1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && dist[nx][ny] > dist[x][y] + grid[nx][ny]) {
dist[nx][ny] = dist[x][y] + grid[nx][ny];
q.emplace(nx, ny);
}
}
}
return dist[m - 1][n - 1] < health;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | func findSafeWalk(grid [][]int, health int) bool {
m, n := len(grid), len(grid[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[0][0] = grid[0][0]
q := [][2]int{{0, 0}}
dirs := []int{-1, 0, 1, 0, -1}
for len(q) > 0 {
curr := q[0]
q = q[1:]
x, y := curr[0], curr[1]
for i := 0; i < 4; i++ {
nx, ny := x+dirs[i], y+dirs[i+1]
if nx >= 0 && nx < m && ny >= 0 && ny < n && dist[nx][ny] > dist[x][y]+grid[nx][ny] {
dist[nx][ny] = dist[x][y] + grid[nx][ny]
q = append(q, [2]int{nx, ny})
}
}
}
return dist[m-1][n-1] < health
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | function findSafeWalk(grid: number[][], health: number): boolean {
const m = grid.length;
const n = grid[0].length;
const dist: number[][] = Array.from({ length: m }, () => Array(n).fill(Infinity));
dist[0][0] = grid[0][0];
const q: [number, number][] = [[0, 0]];
const dirs = [-1, 0, 1, 0, -1];
while (q.length > 0) {
const [x, y] = q.shift()!;
for (let i = 0; i < 4; i++) {
const nx = x + dirs[i];
const ny = y + dirs[i + 1];
if (
nx >= 0 &&
nx < m &&
ny >= 0 &&
ny < n &&
dist[nx][ny] > dist[x][y] + grid[nx][ny]
) {
dist[nx][ny] = dist[x][y] + grid[nx][ny];
q.push([nx, ny]);
}
}
}
return dist[m - 1][n - 1] < health;
}
|