力扣:6081、到达角落需要移除障碍物的最小数目

95 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

6081. 到达角落需要移除障碍物的最小数目

题目描述

给你一个下标从 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 个障碍物,创建出可行的路径。

数据范围

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 105
  • 2 <= m * n <= 105
  • grid[i][j] 为 0 或 1
  • grid[0][0] == grid[m - 1][n - 1] == 0

问题解析

标准的bfs问题,我们用队列来跑,用一个二维数组v来标记走过的路,v[i] [j]记录的是到达grid[i][j]所要花费的最低费用(初始化为一个很大的数)。

初始先将起点入队,同时要记录到达当前位置所要花费的费用,然后我们上下左右四个方向跑,只有不越界而且到达下一个格子所花的费用小于v记录的费用时我们才往那个方向走,将当前坐标入队并且更新v中所花费的费用。

最后返回v数组右下角格子的值即可。

AC代码

class Solution {
public:
    int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
    int minimumObstacles(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        queue<pair<pair<int, int>, int>>que;
        que.push({ {0,0},grid[0][0] });
        vector<vector<int>>v(n, vector<int>(m, 1e9));
        v[0][0] = grid[0][0];
        while (!que.empty())
        {
            int len = que.size();
            for (int i = 0; i < len; i++)
            {
                auto t = que.front();
                que.pop();
                int x = t.first.first, y = t.first.second;
                for (int j = 0; j < 4; j++)
                {
                    int a = x + dx[j], b = y + dy[j];
                    if (a >= 0 && a < n && b >= 0 && b < m&&(v[a][b]==1e9||v[a][b]>v[x][y]+grid[a][b]))
                    {
                        v[a][b] = min(v[a][b], v[x][y] + grid[a][b]);
                        que.push({ {a,b},v[a][b] });
                    }
                }
            }
        }
        return v[n - 1][m - 1];
    }
};