JAVA程序設計:逃離大迷宮(LeetCode:1036)

在一個 10^6 x 10^6 的網格中,每個網格塊的座標爲 (x, y),其中 0 <= x, y < 10^6。

我們從源方格 source 開始出發,意圖趕往目標方格 target。每次移動,我們都可以走到網格中在四個方向上相鄰的方格,只要該方格不在給出的封鎖列表 blocked 上。

只有在可以通過一系列的移動到達目標方格時才返回 true。否則,返回 false。

 

示例 1:

輸入:blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
輸出:false
解釋:
從源方格無法到達目標方格,因爲我們無法在網格中移動。
示例 2:

輸入:blocked = [], source = [0,0], target = [999999,999999]
輸出:true
解釋:
因爲沒有方格被封鎖,所以一定可以到達目標方格。
 

提示:

0 <= blocked.length <= 200
blocked[i].length == 2
0 <= blocked[i][j] < 10^6
source.length == target.length == 2
0 <= source[i][j], target[i][j] < 10^6
source != target

思路:由於方格圖的面積很大,如果我們一味的走向答案則必定會超時,而我們觀察到blocked數組只有200的大小,因此它所能包住的區域是有限的,因此我們可以仍然採用一般的BFS方法,只是我們需要讓其能夠提前退出,而經分析我們可以知道當移動次數超過20000次左右就能證明其一定能夠通過一條路徑到達target(換句話說,就是包不住),而雖然起點包不住,但是終點有可能包住的,因此我們需要把終點看做起點再來一遍。

class Solution {

    private int num;
    private boolean flag;
    private int[] dx = new int[]{0, 0, 1, -1};
    private int[] dy = new int[]{1, -1, 0, 0};
    private Map<String, Boolean> map;
    private Map<String, Boolean> vised;

    public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {

        map = new HashMap<>();

        int len = blocked.length;
        for (int i = 0; i < len; i++) {
            String s = String.valueOf(blocked[i][0]) + "#" + String.valueOf(blocked[i][1]);
            map.put(s, true);
        }

        return jud(blocked, source, target) && jud(blocked, target, source);

    }

    private boolean jud(int[][] blocked, int[] source, int[] target) {

        num = 0;
        flag = false;
        vised = new HashMap<>();

        bfs(source[0], source[1], target[0], target[1]);

        return flag;

    }

    private void bfs(int x, int y, int target_x, int target_y) {

        Queue<int[]> q = new LinkedList<>();

        num = 1;
        q.add(new int[]{x, y});
        String s = String.valueOf(x) + "#" + String.valueOf(y);
        vised.put(s, true);

        while (!q.isEmpty()) {
            int[] now = q.poll();
            if (now[0] == target_x && now[1] == target_y) {
                flag = true;
                return;
            }
            for (int i = 0; i < 4; i++) {
                int xx = now[0] + dx[i];
                int yy = now[1] + dy[i];
                String ss = String.valueOf(xx) + "#" + String.valueOf(yy);

                if (xx < 0 || yy < 0 || check(xx, yy) || vised.containsKey(ss))
                    continue;
                num++;
                if (num >= 20000) {
                    flag = true;
                    return;
                }
                q.add(new int[]{xx, yy});
                vised.put(ss, true);
            }
        }
    }

    private boolean check(int x, int y) {
        String s = String.valueOf(x) + "#" + String.valueOf(y);
        return map.containsKey(s);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章