1263. Minimum Moves to Move a Box to Their Target Location

Difficulty:
Related Topics:
Similar Questions:

    Problem

    A 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 an m x n grid of characters grid where each element is a wall, floor, or box.

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

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

      Example 1:

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

    Example 2:

    Input: grid = [["#","#","#","#","#","#"],
                   ["#","T","#","#","#","#"],
                   ["#",".",".","B",".","#"],
                   ["#","#","#","#",".","#"],
                   ["#",".",".",".","S","#"],
                   ["#","#","#","#","#","#"]]
    Output: -1
    

    Example 3:

    Input: grid = [["#","#","#","#","#","#"],
                   ["#","T",".",".","#","#"],
                   ["#",".","#","B",".","#"],
                   ["#",".",".",".",".","#"],
                   ["#",".",".",".","S","#"],
                   ["#","#","#","#","#","#"]]
    Output: 5
    Explanation: push the box down, left, left, up and up.
    

      Constraints:

    Solution

    class Solution {
        private int n;
        private int m;
        private char[][] grid;
        private final int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
    
        public int minPushBox(char[][] grid) {
            n = grid.length;
            m = grid[0].length;
            this.grid = grid;
            int[] box = new int[2];
            int[] target = new int[2];
            int[] player = new int[2];
            findLocations(box, target, player);
            Queue<int[]> q = new LinkedList<>();
            q.offer(new int[] {box[0], box[1], player[0], player[1]});
            // for 4 directions
            boolean[][][] visited = new boolean[n][m][4];
            int steps = 0;
            while (!q.isEmpty()) {
                int size = q.size();
                while (size-- > 0) {
                    int[] cur = q.poll();
                    if (cur != null && cur[0] == target[0] && cur[1] == target[1]) {
                        return steps;
                    }
                    for (int i = 0; i < 4; i++) {
                        if (cur != null) {
                            int[] newPlayerLoc = new int[] {cur[0] + dirs[i][0], cur[1] + dirs[i][1]};
                            int[] newBoxLoc = new int[] {cur[0] - dirs[i][0], cur[1] - dirs[i][1]};
                            if (visited[cur[0]][cur[1]][i]
                                    || isOutOfBounds(newPlayerLoc, newBoxLoc)
                                    || !isReachable(newPlayerLoc, cur)) {
                                continue;
                            }
                            visited[cur[0]][cur[1]][i] = true;
                            q.offer(new int[] {newBoxLoc[0], newBoxLoc[1], cur[0], cur[1]});
                        }
                    }
                }
                steps++;
            }
            return -1;
        }
    
        private boolean isReachable(int[] targetPlayerLoc, int[] cur) {
            boolean[][] visited = new boolean[n][m];
            visited[cur[0]][cur[1]] = true;
            visited[cur[2]][cur[3]] = true;
            Queue<int[]> q = new LinkedList<>();
            q.offer(new int[] {cur[2], cur[3]});
            while (!q.isEmpty()) {
                int[] playerLoc = q.poll();
                if (playerLoc[0] == targetPlayerLoc[0] && playerLoc[1] == targetPlayerLoc[1]) {
                    return true;
                }
                for (int[] d : dirs) {
                    int x = playerLoc[0] + d[0];
                    int y = playerLoc[1] + d[1];
                    if (isOutOfBounds(x, y) || visited[x][y]) {
                        continue;
                    }
                    visited[x][y] = true;
                    q.offer(new int[] {x, y});
                }
            }
            return false;
        }
    
        private boolean isOutOfBounds(int[] player, int[] box) {
            return isOutOfBounds(player[0], player[1]) || isOutOfBounds(box[0], box[1]);
        }
    
        private boolean isOutOfBounds(int x, int y) {
            return (x < 0 || y < 0 || x == n || y == m || grid[x][y] == '#');
        }
    
        private void findLocations(int[] box, int[] target, int[] player) {
            boolean p = false;
            boolean t = false;
            boolean b = false;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (grid[i][j] == 'S') {
                        player[0] = i;
                        player[1] = j;
                        p = true;
                    } else if (grid[i][j] == 'T') {
                        target[0] = i;
                        target[1] = j;
                        t = true;
                    } else if (grid[i][j] == 'B') {
                        box[0] = i;
                        box[1] = j;
                        b = true;
                    }
                    if (p && b && t) {
                        // found all
                        return;
                    }
                }
            }
        }
    }
    

    Explain:

    nope.

    Complexity: