Given a m * n
grid, where each cell is either 0
(empty) or 1
(obstacle). In one step, you can move up, down, left or right from and to an empty cell.
Return the minimum number of steps to walk from the upper left corner (0, 0)
to the lower right corner (m-1, n-1)
given that you can eliminate at most k
obstacles. If it is not possible to find such walk return -1.
Example 1:
Input:
grid =
[[0,0,0],
[1,1,0],
[0,0,0],
[0,1,1],
[0,0,0]],
k = 1
Output: 6
Explanation:
The shortest path without eliminating any obstacle is 10.
The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2)
思路://为什么需要第三维度信息,是因为到x,y我可以以好几种方式到达,也就是不remove 1,
//和remove多个1之后到达,虽然坐标一样,但是状态是不一样的
class Solution {
class Node {
public int x;
public int y;
public int usedk;
public Node(int x, int y, int usedk) {
this.x = x;
this.y = y;
this.usedk = usedk;
}
}
public int shortestPath(int[][] grid, int k) {
int m = grid.length;
int n = grid[0].length;
Queue<Node> queue = new LinkedList<>();
boolean[][][] visited = new boolean[m][n][k + 1];
queue.offer(new Node(0, 0, k));
visited[0][0][k] = true;
int step = 0;
int[][] dirs = new int[][]{{0,1},{0,-1},{-1,0},{1,0}};
while(!queue.isEmpty()) {
int size = queue.size();
for(int i = 0; i < size; i++) {
Node node = queue.poll();
int x = node.x;
int y = node.y;
if(x == m - 1 && y == n - 1) {
return step;
}
for(int[] dir: dirs) {
int nx = x + dir[0];
int ny = y + dir[1];
// 注意这个nextk,必须在里面,因为每次move都必须从原来的node usedk出发;
int nextk = node.usedk;
if(0 <= nx && nx < m && 0 <= ny && ny < n) {
if(grid[nx][ny] == 1) {
nextk--;
}
if(nextk >= 0 && !visited[nx][ny][nextk]) {
queue.offer(new Node(nx, ny, nextk));
visited[nx][ny][nextk] = true;
}
}
}
}
step++;
}
return -1;
}
}