6081. 到达角落需要移除障碍物的最小数目
给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n 。每个单元格都是两个值之一:
0 表示一个 空 单元格,
1 表示一个可以移除的 障碍物 。
你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
现在你需要从左上角 (0,0) 移动到右下角 (m -1, n -1) ,返回需要移除的障碍物的 最小 数目。
示例 1:
输入:grid =[[0,1,1],[1,1,0],[1,1,0]]
输出:2
解释:可以移除位于 (0,1) 和 (0,2) 的障碍物来创建从 (0,0) 到 (2,2) 的路径。
可以证明我们至少需要移除两个障碍物,所以返回 2 。
注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。
示例 2:
输入:grid =[[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]]
输出:0
解释:不移除任何障碍物就能从 (0,0) 到 (2,4) ,所以返回 0 。
提示:
m == grid.length
n == grid[i].length
1<= m, n <=1052<= m * n <=105
grid[i][j] 为 0 或 1
grid[0][0]== grid[m -1][n -1]==0
解法
方法1:01-BFS
int m, n;int[][] dirs ={{0,1},{0,-1},{1,0},{-1,0}};publicintminimumObstacles(int[][] grid){
m = grid.length;
n = grid[0].length;int[] dist =newint[m * n];Arrays.fill(dist,Integer.MAX_VALUE);
dist[0]=0;boolean[] vis =newboolean[m * n];Deque<Integer> deque =newArrayDeque<>();
deque.offerFirst(0);while(!deque.isEmpty()){int cur_pos = deque.pollFirst();if(vis[cur_pos]){continue;}
vis[cur_pos]=true;int x = cur_pos / n, y = cur_pos % n;for(int i =0; i <4; i++){int nx = x + dirs[i][0], ny = y + dirs[i][1];int new_pos = nx * n + ny;if(nx <0|| nx >= m || ny <0|| ny >= n){continue;}int g = grid[x][y];if(dist[cur_pos]+ g < dist[new_pos]){
dist[new_pos]= dist[cur_pos]+ g;//01广度优先搜索,将0的那个点加入到队首,1的那个点加入到对尾if(g ==0){
deque.offerFirst(new_pos);}else{
deque.offerLast(new_pos);}}}}return dist[m * n -1];}
另 ,数组写法,不转换坐标
int[][] dirs ={{-1,0},{1,0},{0,-1},{0,1}};publicintminimumObstacles(int[][] grid){int m = grid.length;int n = grid[0].length;int[][] dis =newint[m][n];for(int i =0; i < m; i++){Arrays.fill(dis[i],Integer.MAX_VALUE);}
dis[0][0]=0;Deque<int[]> q =newArrayDeque<>();
q.addFirst(newint[]{0,0});while(!q.isEmpty()){int[] p = q.pollFirst();int x = p[0], y = p[1];for(int[] d : dirs){int nx = x + d[0], ny = y + d[1];if(0<= nx && nx < m &&0<= ny && ny < n){int g = grid[nx][ny];if(dis[x][y]+ g < dis[nx][ny]){
dis[nx][ny]= dis[x][y]+ g;if(g ==0) q.addFirst(newint[]{nx, ny});else q.addLast(newint[]{nx, ny});}}}}return dis[m -1][n -1];}
方法2:01BFS
classPoint{int value;int pos;Point(){}publicPoint(int value,int pos){this.value = value;this.pos = pos;}}int[][] dirs =newint[][]{{0,1},{0,-1},{1,0},{-1,0}};publicintminimumObstacles(int[][] grid){int m = grid.length;int n = grid[0].length;int[][] dist =newint[m][n];for(int r =0; r < m; r++){Arrays.fill(dist[r],Integer.MAX_VALUE);}//按value 从小到大排序PriorityQueue<Point> pq =newPriorityQueue<>((o1, o2)-> o1.value - o2.value);
pq.offer(newPoint(grid[0][0],0));
dist[0][0]=0;while(!pq.isEmpty()){Point cur = pq.poll();int r = cur.pos / n, c = cur.pos % n;int value = cur.value;if(dist[r][c]< value){continue;}if(r == m -1&& c == n -1){return value;}for(int k =0; k <4; k++){int nr = r + dirs[k][0], nc = c + dirs[k][1];int cost =(k +1== grid[r][c]?0:1);if(0<= nr && nr < m &&0<= nc && nc < n){int next_value = grid[nr][nc]+ value;if(dist[nr][nc]> next_value){
dist[nr][nc]= next_value;
pq.offer(newPoint(next_value, nr * n + nc));}}}}return dist[m -1][n -1];}