问题
解题
- 题干中的求最短距离,先想到BFS,然后用BFS+队列实现
- 又由于题干中需要维护一个花费值K,如果假设K为每个格子还能移除K个障碍物,则每个格子都可能有K个状态,用
visited[i][j][k]
表示点i,j格子还能消除k个障碍物的状态是否出现过。 - 用step维护最短路径,类似于树的层序遍历,每次扩展一层,该层的step比上一层+1.
- 如果扩展到的点为0,则剩下的消除数rest不变,否则-1,如果rest<0则跳过这个状态
- 注意:这里需要维护三个状态,横纵坐标以及该点的消除数K,因此需要自定义结构体
class Solution {
int m, n;
public int shortestPath(int[][] grid, int k) {
this.m = grid.length;
this.n = grid[0].length;
if(m <= 1 && n <= 1) return 0;
Queue<Status> queue = new LinkedList<>();
boolean[][][] visited = new boolean[m][n][k+1];// 访问同一个坐标可以有k个状态,这些状态必须都要考虑的
visited[0][0][k] = true;//初始状态
queue.add(new Status(0, 0, k));
int[] dx = {0,0,1,-1};
int[] dy = {1,-1,0,0};
int step = 0;
while(queue.size() > 0){
step ++;//枚举这一层
int cnt = queue.size();
for(int j = 0; j < cnt; j ++){
Status st = queue.poll();
int row = st.row;
int col = st.col;
int rest = st.rest;
for(int i = 0; i < 4; i ++){
int x = row + dx[i];
int y = col + dy[i];
if(x >= 0 && x < m && y >= 0 && y < n){
if (grid[x][y] == 0 && !visited[x][y][rest]) {
if (x == m - 1 && y == n - 1) {//如果到右下角了就提前剪枝
return step;
}
queue.offer(new Status(x, y, rest));
visited[x][y][rest] = true;
} else if (grid[x][y] == 1 && rest > 0 && !visited[x][y][rest - 1]) {
//消除1个障碍物,直到允许清理的障碍物为0为止
queue.offer(new Status(x, y, rest - 1));
visited[x][y][rest - 1] = true;
}
}
}
}
}
return -1;
}
}
class Status{
int row;
int col;
int rest;
public Status(int row, int col, int rest){
this.row = row;
this.col = col;
this.rest = rest;
}
}