Leetcode6081. 到达角落需要移除障碍物的最小数目-----0-1BFS

题目表述

给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n 。每个单元格都是两个值之一:

  • 0 表示一个 空 单元格,
  • 1 表示一个可以移除的 障碍物 。
    你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。

现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1) ,返回需要移除的障碍物的 最小 数目。

示例:

输入:grid = [[0,1,1],[1,1,0],[1,1,0]]
输出:2
解释:可以移除位于 (0, 1) 和 (0, 2) 的障碍物来创建从 (0, 0) 到 (2, 2) 的路径。
可以证明我们至少需要移除两个障碍物,所以返回 2 。
注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。

0-1广度优先搜索

常规的广度优先搜索可以找出在边权均为1时的单源最短路,然而在建模中,边权除了1之外也可能为0。
在常规的广度优先搜索中,我们使用队列作为维护节点的数据结构,就保证了从队列中取出的节点,它们与源点之间的距离是单调递增的。然而如果边权可能为0,就会出现如下的情况:

  • 源点s被取出队列;
  • 源点 s 到节点 v1 有一条权值为 11 的边,将节点 v1 加入队列;

  • 源点 s到节点 v2 有一条权值为 0 的边,将节点 v2 加入队列;

此时节点v2就会在节点v1之后被取出队列,但节点v2与原点之间的距离反而较小,这样就破坏了广度优先搜索正确性的基础。

可以使用双端队列代替普通的队列作为维护节点的数据结构,当任意节点u被取出队列时,如果它到某节点vi有一条权值为0的边,那么就将节点vi加入双端队列的队首,如果它到某节点vj有一条权值为1的边,那么和常规的bfs相同,将节点vj加入到双端队列的队尾。
0-1 广度优先搜索的实现其实与 Dijkstra 算法非常相似。在 Dijkstra 算法中,我们用优先队列保证了距离的单调递增性。而在 0-1 广度优先搜索中,实际上任意时刻队列中的节点与源点的距离均为 d 或 d+1(其中 d 为某一非负整数),并且所有与源点距离为 d 的节点都出现在队首附近,所有与源点距离为 d + 1 的节点都出现在队尾附近。因此,只要使用双端队列,对于边权为 0 和 1 的两种情况分别将对应节点添加至队首和队尾,就保证了距离的单调递增性。

class Solution {

    public int minimumObstacles(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] dis = new int[m][n];
        for(int i = 0; i < m;i++){
            Arrays.fill(dis[i], Integer.MAX_VALUE);
        }
        dis[0][0] = 0;
        int[][] dirs = {{1,0}, {-1, 0}, {0, -1}, {0,1}};
        Deque<int[]> que = new ArrayDeque<>();
        que.offer(new int[]{0,0});
        while(!que.isEmpty()){
            int[] cur = que.poll();
            for(int[] dir : dirs){
                int x = dir[0] + cur[0];
                int y = dir[1] + cur[1];
                if(x < 0 || y < 0 || x >= m || y >= n) continue;
                if(dis[cur[0]][cur[1]] + grid[x][y] < dis[x][y]){
                    dis[x][y] = dis[cur[0]][cur[1]] + grid[x][y];
                    if(grid[x][y] == 0) que.addFirst(new int[]{x,y});
                    else{
                        que.addLast(new int[]{x,y});
                    }
                }
            }
        }
        return dis[m-1][n-1];
    }

}
posted @ 2022-06-04 16:43  YoungerWb  阅读(57)  评论(0编辑  收藏  举报