1293. 网格中的最短路径
给你一个 m * n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。每一步,您都可以在空白单元格中上、下、左、右移动。
如果您 最多 可以消除 k 个障碍物,请找出从左上角 (0,0) 到右下角 (m-1, n-1) 的最短路径,并返回通过该路径所需的步数。如果找不到这样的路径,则返回 -1 。
示例 1:
输入: grid =[[0,0,0],[1,1,0],[0,0,0],[0,1,1],[0,0,0]], k =1
输出:6
解释:
不消除任何障碍的最短路径是 10。
消除位置 (3,2) 处的障碍后,最短路径是 6 。该路径是 (0,0)->(0,1)->(0,2)->(1,2)->(2,2)->(3,2)->(4,2).
示例 2:
输入:grid =[[0,1,1],[1,1,1],[1,0,0]], k =1
输出:-1
解释:我们至少需要消除两个障碍才能找到这样的路径。
提示:
grid.length == m
grid[0].length == n
1<= m, n <=401<= k <= m*n
grid[i][j] 是 0 或 1
grid[0][0]== grid[m-1][n-1]==0
解法
方法1:BFS
int m, n;//右 下 左 上int[][] dirs ={{0,1},{1,0},{0,-1},{-1,0}};//我们还可以对搜索空间进行优化。注意到题目中 k 的上限为 m * n,但考虑一条从 (0, 0) 向下走到 (m - 1, 0) 再向右走到// (m - 1, n - 1) 的路径,它经过了 m + n - 1 个位置,其中起点 (0, 0) 和终点 (m - 1, n - 1) 没有障碍物,// 那么这条路径上最多只会有 m + n - 3 个障碍物。因此我们可以将 k 的值设置为 m + n - 3 与其本身的较小值// min(k, m + n - 3),将广度优先搜索的时间复杂度从 O(MNK) 降低至 (MN∗min(M+N,K))publicintshortestPath(int[][] grid,int k){
m = grid.length;
n = grid[0].length;//case ->//[[0]]//1if(m ==1&& n ==1)return0;// if ( k >= m + n - 3){// return m + n - 2;// }// k = Math.min(k, m + n - 3);boolean[][][] vis =newboolean[m][n][k +1];Queue<Position> q =newLinkedList<>();//标记访问的状态
q.offer(newPosition(0,0, k));
vis[0][0][k]=true;int steps =0;while(!q.isEmpty()){int size = q.size();
steps++;for(int i =0; i < size; i++){Position p = q.poll();for(int[] d : dirs){int nx = p.x + d[0], ny = p.y + d[1];if(nx >= m || nx <0|| ny >= n || ny <0){continue;}if(grid[nx][ny]==0&&!vis[nx][ny][p.count]){if(nx == m -1&& ny == n -1){return steps;}
q.offer(newPosition(nx, ny, p.count));
vis[nx][ny][p.count]=true;}elseif(grid[nx][ny]==1&& p.count >0&&!vis[nx][ny][p.count -1]){
q.offer(newPosition(nx, ny, p.count -1));
vis[nx][ny][p.count -1]=true;}}}}return-1;}classPosition{int x, y;int count;//当前状态下还可以经过多少个障碍物,此数量为非负publicPosition(int x,int y,int count){this.x = x;this.y = y;this.count = count;}}