给你一个下标从 0 开始的二维整数数组
grid,数组大小为m x n。每个单元格都是两个值之一:
0表示一个 空 单元格,
1表示一个可以移除的 障碍物 。你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
现在你需要从左上角
(0, 0)移动到右下角(m - 1, n - 1),返回需要移除的障碍物的 最小 数目。
c++
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
class Solution {
public:
    // 图的边权只有 0 和 1 使用 0-1bfs 也叫 双端队列bfs
    int minimumObstacles(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        int dis[m][n];
        memset(dis, 0x3f, sizeof dis);
        dis[0][0] = 0;
        deque<pair<int, int>> q;
        q.push_front({0, 0});
        while (!q.empty()) {
            int x = q.front().first, y = q.front().second;
            q.pop_front();
            for (int i = 0; i < 4; i++) {
                int a = x + dx[i], b = y + dy[i];
                if (a >= 0 && a < m && b >= 0 && b < n) {
                    int g = grid[a][b];
                    if (dis[x][y] + g < dis[a][b]) {
                        dis[a][b] = dis[x][y] + g;
                        g == 0 ? q.push_front({a, b}) : q.push_back({a, b});
                        // 边权为 0 就入队头 边权为 1 就入队尾
                    }
                }
            }
        }
        return dis[m - 1][n - 1];
    }
};现在你将作为玩家参与游戏,按规则将箱子
'B'移动到目标位置'T':
- 玩家用字符
'S'表示,只要他在地板上,就可以在网格中向上、下、左、右四个方向移动。- 地板用字符
'.'表示,意味着可以自由行走。- 墙用字符
'#'表示,意味着障碍物,不能通行。- 箱子仅有一个,用字符
'B'表示。相应地,网格上有一个目标位置'T'。- 玩家需要站在箱子旁边,然后沿着箱子的方向进行移动,此时箱子会被移动到相邻的地板单元格。记作一次「推动」。
- 玩家无法越过箱子。
返回将箱子推到目标位置的最小 推动 次数,如果无法做到,请返回
-1。
c++
struct point {
    int px, py, bbx, bby, d;
}; // 用四元组表示状态
class Solution {
public:
    int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
    bool st[20][20][20][20] = {0};
    int minPushBox(vector<vector<char>>& grid) {
        int m = grid.size(), n = grid[0].size();
        int bx, by, tx, ty, sx, sy;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (grid[i][j] == 'S') sx = i, sy = j;
                else if (grid[i][j] == 'B') bx = i, by = j;
                else if (grid[i][j] == 'T') tx = i, ty = j;
        
        deque<point> q;
        q.push_back(point{sx, sy, bx, by, 0});
        st[sx][sy][bx][by] = true;
        
        auto check = [&](int x, int y) 
        {
            return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] != '#';
        };
        while (q.size())
        {
            auto t = q.front();
            q.pop_front();
            int px = t.px, py = t.py, bbx = t.bbx, bby = t.bby, d = t.d;
            if (bbx == tx && bby == ty) return d;
            for (int i = 0; i < 4; i++)
            {
                int npx = px + dx[i], npy = py + dy[i];
                if (!check(npx, npy)) continue;
                if (npx == bbx && npy == bby)
                {
                    int nbx = bbx + dx[i], nby = bby + dy[i];
                    if (!check(nbx, nby) || st[npx][npy][nbx][nby]) continue;
                    st[npx][npy][nbx][nby] = true;
                    q.push_back(point{npx, npy, nbx, nby, d + 1}); // 箱子动了
                }
                else if (!st[npx][npy][bbx][bby])
                {
                    q.push_front(point{npx, npy, bbx, bby, d}); // 箱子未动
                    st[npx][npy][bbx][bby] = true;
                }
            }
        }
        return -1;
    }
};