在一個 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);
}
}