算法思路:
- 如果路径中有障碍物,必须移除掉才能进行下一步;如果路径中无障碍物,就可以一直走,直到遇到障碍物。所以体现了层次遍历的特点,只是针对2种不同情况分别做层次遍历。
- 第一种层次遍历就是遇到障碍就算一层,另一种层次遍历是以无障碍物的点充分扩散,将遇到的所有新的障碍物作为新的一层。
class Solution {
vector<pair<int,int>> dirs={{1,0},{-1,0},{0,1},{0,-1}};
public:
int minimumObstacles(vector<vector<int>>& grid) {
int m=grid.size();
int n=grid[0].size();
vector<vector<int>> visited(m,vector<int>(n,0));//标记数组
queue<pair<int,int>> q;
q.emplace(0,0);
visited[0][0]=1;
int step=0;
while(!q.empty()){
int size=q.size();
while(size--){
auto [i,j]=q.front();q.pop();
for(auto & [dx,dy]:dirs){
int x=i+dx,y=j+dy;
if(x<0||x>=m||y<0||y>=n) continue;
if(visited[x][y]) continue;
if(grid[x][y]==1){//第一种,直接当作一层
q.emplace(x,y);
visited[x][y]=1;
}else{
for(auto & [ii,jj]:transair(grid,visited,i,j)){//第二种,将遇到的所有新的障碍算作新的一层
if(ii==m-1 && jj==n-1) return step; //特判加在这里
q.emplace(ii,jj);
visited[ii][jj]=1;
}
}
}
}
step++;
}
return 0;
}
vector<pair<int,int>> transair(vector<vector<int>>&grid,vector<vector<int>>&visited,int x0,int y0){
int m=grid.size();
int n=grid[0].size();
queue<pair<int,int>> q;
visited[x0][y0]=1;
q.emplace(x0,y0);
vector<pair<int,int>> ret;
while(!q.empty()){
auto [i,j]=q.front();q.pop();
for(auto &[dx,dy]:dirs){
int x=i+dx,y=j+dy;
if(x<0||x>=m||y<0||y>=n) continue;
if(visited[x][y]) continue;
if(grid[x][y]==1 || x==m-1 && y==n-1){
ret.emplace_back(x,y); //是障碍物或终点就作为下一层
}else{
q.emplace(x,y); //是空气就继续扩散
visited[x][y]=1;
}
}
}
return ret;
}
};