Java - BFS easy to understand solution
\nclass Solution {\n    public int minPushBox(char[][] grid) {\n        if (grid == null || grid.length == 0 || grid[0].length == 0) {\n            return -1;\n
```\nclass Solution {\n    public int minPushBox(char[][] grid) {\n        if (grid == null || grid.length == 0 || grid[0].length == 0) {\n            return -1;\n        }\n        int[] box = new int[2];\n        int[] player = new int[2];\n        int[] target = new int[2];\n        Map<String, Integer> steps = new HashMap<>();\n        for (int i = 0; i < grid.length; i++) {\n            for (int j = 0; j < grid[0].length; j++) {\n                if (grid[i][j] == \'B\') {\n                    box = new int[] {i, j};\n                } else if (grid[i][j] == \'S\') {\n                    player = new int[] {i, j};\n                } else if (grid[i][j] == \'T\') {\n                    target = new int[] {i, j};\n                }\n            }\n        }\n        int[] dx = new int[] {0, 0, 1, -1};\n        int[] dy = new int[] {1, -1, 0, 0};\n        // so in BFS, instead of save a single point, save both box and player together\n        String start = encode(box[0], box[1], player[0], player[1]);\n        int res = Integer.MAX_VALUE;\n        Queue<String> queue = new LinkedList<>();\n        queue.offer(start);\n        steps.put(start, 0);\n        while (!queue.isEmpty()) {\n            String curr = queue.poll();\n            if (steps.getOrDefault(curr, 0) > res) {\n                continue;\n            }\n            int[] currBox = new int[] {Integer.parseInt(curr.split(":")[0]), Integer.parseInt(curr.split(":")[1])};\n            int[] currPlayer = new int[] {Integer.parseInt(curr.split(":")[2]), Integer.parseInt(curr.split(":")[3])};\n            if (currBox[0] == target[0] && currBox[1] == target[1]) {\n                res = Math.min(res, steps.get(curr));\n                continue;\n            }\n            for (int i = 0; i < 4; i++) {\n                // every step, move player, if player meet the box, push the box.\n                int[] newP = new int[] {currPlayer[0] + dx[i], currPlayer[1] + dy[i]};\n                if (newP[0] < 0 || newP[1] < 0 || newP[0] >= grid.length \n                    || newP[1] >= grid[0].length || grid[newP[0]][newP[1]] == \'#\') {\n                    continue;\n                }\n                if (newP[0] == currBox[0] && newP[1] == currBox[1]) {\n                    int[] newB = new int[] {currBox[0] + dx[i], currBox[1] + dy[i]};\n                    if (newB[0] < 0 || newB[1] < 0 || newB[0] >= grid.length \n                        || newB[1] >= grid[0].length || grid[newB[0]][newB[1]] == \'#\') {\n                        continue;\n                    }\n                    String temp = encode(newB[0], newB[1], newP[0], newP[1]);\n                    if (steps.containsKey(temp) && steps.get(temp) <= steps.get(curr) + 1) {\n                        continue;\n                    }\n                    steps.put(temp, steps.get(curr) + 1);\n                    queue.offer(temp);\n                } else {\n                    // if not meet box, just save it to the queue.\n                    String temp = encode(currBox[0], currBox[1], newP[0], newP[1]);\n                    if (steps.containsKey(temp) && steps.get(temp) <= steps.get(curr) + 1) {\n                        continue;\n                    }\n                    steps.put(temp, steps.get(curr));\n                    queue.offer(temp);\n                }\n            }   \n        }\n        return res == Integer.MAX_VALUE ? -1 : res;\n    }\n    \n    private String encode(int i1, int i2, int i3, int i4) {\n        return i1 + ":" + i2 + ":" + i3 + ":" + i4;\n    }\n}\n```
[]