【搜索】A062_LC_推箱子(雙端隊列 bfs(代辦))

一、Problem

Storekeeper is a game in which the player pushes boxes around in a warehouse trying to get them to target locations.

The game is represented by a grid of size m x n, where each element is a wall, floor, or a box.

Your task is move the box ‘B’ to the target position ‘T’ under the following rules:

  • Player is represented by character ‘S’ and can move up, down, left, right in the grid if it is a floor (empy cell).
  • Floor is represented by character ‘.’ that means free cell to walk.
  • Wall is represented by character ‘#’ that means obstacle (impossible to walk there).
  • There is only one box ‘B’ and one target cell ‘T’ in the grid.
  • The box can be moved to an adjacent free cell by standing next to the box and - then moving in the direction of the box. This is a push.
  • The player cannot walk through the box.

Return the minimum number of pushes to move the box to the target. If there is no way to reach the target, return -1.

在這裏插入圖片描述

Input: grid = [["#","#","#","#","#","#"],
               ["#","T","#","#","#","#"],
               ["#",".",".","B",".","#"],
               ["#",".","#","#",".","#"],
               ["#",".",".",".","S","#"],
               ["#","#","#","#","#","#"]]
Output: 3
Explanation: We return only the number of times the box is pushed.

二、Solution

方法一:bfs

  • 人先走,正常 bfs 即可,如果在換方向時碰到箱子,那麼這個方向時不可行的,因爲我只是想枚舉人的座標。
  • 如果找到相鄰位置是箱子(曼哈頓距爲 1),那麼計算出箱子在哪個方向,然後就是將箱子的位置的同方向 k 的下一個位置 push_back 到雙端隊列中,此時距離記得加 1(ps:人移動時的距離是不用加 1)

細節:

  1. 人的位置總是在隊列中的前面,因爲這樣能快速訪問到箱子,而且可以枚舉到人從各個方向將箱子推到終點的最短距離,避免疏漏。
  2. 因爲有箱子的存在,所以會有兩個座標的狀態表示。
class Solution {
    int n, m;
    final static int[][] d = { {1,0},{0,-1},{0,1},{-1,0} };
    public int minPushBox(char[][] g) {
        n = g.length; m = g[0].length;
        int[][][][] f = new int[n][m][n][m];
        
        int Px = 0, Py = 0, Bx = 0, By = 0, Tx = 0, Ty = 0;

        for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            if (g[i][j] == 'S') {
                Px = i; Py = j;
                g[i][j] = '.';
            } else if (g[i][j] == 'B') {
                Bx = i; By = j;
                g[i][j] = '.';
            } else if (g[i][j] == 'T') {
                Tx = i; Ty = j;
                g[i][j] = '.';
            }
        }
        for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            f[i][j][i][j] = -1;
        Deque<Pos> q = new ArrayDeque<>();
        q.add(new Pos(Px, Py, Bx, By));
        f[Px][Py][Bx][By] = 0;

        while (!q.isEmpty()) {
            Pos cur = q.poll();
            int px = cur.px, py = cur.py, bx = cur.bx, by = cur.by;
            if (bx == Tx && by == Ty) {
                // System.out.println(111);
                return f[px][py][bx][by];
            }
            for (int k = 0; k < 4; k++) {
                int npx = px + d[k][0], npy = py + d[k][1];
                // System.out.println(npx + " " + npy);
                if (!inArea(npx, npy) || g[npx][npy] != '.')
                    continue;
                if (npx == bx && npy == by || f[npx][npy][bx][by] >= 0)
                    continue;
                q.addFirst(new Pos(npx, npy, bx, by));
                f[npx][npy][bx][by] = f[px][py][bx][by];
            }
            if (Math.abs(px-bx) + Math.abs(py-by) == 1) {
                // System.out.println(111);
                int k;
                for (k = 0; k < 4; k++) {
                    int nx = px + d[k][0], ny = py + d[k][1];
                    if (nx == bx && ny == by)
                        break;
                }
                int nbx = bx + d[k][0], nby = by + d[k][1];
                if (!inArea(nbx, nby) || g[nbx][nbx] != '.' || f[bx][by][nbx][nby] >= 0)
                    continue;
                q.add(new Pos(bx, by, nbx, nby));
                f[bx][by][nbx][nby] = f[px][py][bx][by] + 1;
                // System.out.println(f[bx][by][nbx][nby]);
            }
        }
        return -1;
    }
    boolean inArea(int x, int y) {
        return x >= 0 && x < n && y >= 0 && y < m;
    }
    class Pos {
        int px, py, bx, by;
        public Pos(int px, int py, int bx, int by) {
            this.px = px;
            this.py = py;
            this.bx = bx;
            this.by = by;
        }
    }
}

複雜度分析

  • 時間複雜度:O(...)O(...)
  • 空間複雜度:O(...)O(...)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章