题目描述:
给你一个 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 <= 40
1 <= k <= m*n
grid[i][j] == 0 or 1
grid[0][0] == grid[m-1][n-1] == 0
思路:
1、广度优先遍历
2、多次走过某一网格的情况该怎么处理。记录每次经过该网格时的K值,如果当前经过时的K值大于上一次经过的K值,则可以走该网格。因为K值越大,从该网格走过时走的越远
代码:
class Solution {
public:
int shortestPath(vector<vector<int>>& grid, int k) {
int m=grid.size(),n=grid[0].size();
if(m==1&&n==1)return 0;
if(k>=m+n-2)return m+n-2;
queue<vector<int>>q;
vector<int>temp(4);
vector<vector<int>>status(m,vector<int>(n));
int res=INT_MAX,x,y;
int disx[4]={1,-1,0,0};
int disy[4]={0,0,-1,1};
q.push(vector<int>{0,0,0,k});
while(!q.empty())
{
temp=q.front();
q.pop();
temp[2]++;
for(int i=0;i<4;i++)
{
x=temp[0]+disx[i];
y=temp[1]+disy[i];
if(x>=m||x<0||y>=n||y<0||grid[x][y]==2)continue;
if(temp[3]==0&&grid[x][y]==1)continue;
if(x==m-1&&y==n-1)
{
res=min(res,temp[2]);
continue;
}
if(temp[3]>status[x][y])
{
if(grid[x][y]==1)q.push(vector<int>{x,y,temp[2],temp[3]-1});
else if(grid[x][y]==0) q.push(vector<int>{x,y,temp[2],temp[3]});
status[x][y]=temp[3];
}
}
}
return res==INT_MAX?-1:res;
}
};