You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.7 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_01_3_week;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
// 在一个10^6 * 10^6的网格中
// source = [sx, sy]是出发位置target = [tx, ty]是目标位置
// 数组blocked是封锁的方格列表
// blocked[i] = [xi, yi] 表示(xi, yi)的方格是禁止通行的
// 每次移动都可以走上、下、左、右四个方向
// 但是来到的位置不能在封锁列表blocked上
// 同时不允许走出网格
// 如果从source能到达target返回 true。否则返回false。
// 测试链接 : https://leetcode.com/problems/escape-a-large-maze/
// 本题最强的优化是一个剪枝
public class Code02_EscapeALargeMaze {
public static long offset = 1000000;
public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
int n = blocked.length;
int maxPoints = n * (n - 1) / 2;
HashSet<Long> blockSet = new HashSet<>();
for (int i = 0; i < n; i++) {
blockSet.add((long) blocked[i][0] * offset + blocked[i][1]);
}
return bfs(source[0], source[1], target[0], target[1], maxPoints, blockSet)
&& bfs(target[0], target[1], source[0], source[1], maxPoints, blockSet);
}
public static boolean bfs(int fromX, int fromY, int toX, int toY, int maxPoints, HashSet<Long> blockSet) {
HashSet<Long> visited = new HashSet<>();
Queue<Long> queue = new LinkedList<>();
visited.add((long) fromX * offset + fromY);
queue.add((long) fromX * offset + fromY);
while (!queue.isEmpty() && (visited.size() <= maxPoints)) {
long cur = queue.poll();
long curX = cur / offset;
long curY = cur - curX * offset;
if (findAndAdd(curX - 1, curY, toX, toY, blockSet, visited, queue)
|| findAndAdd(curX + 1, curY, toX, toY, blockSet, visited, queue)
|| findAndAdd(curX, curY - 1, toX, toY, blockSet, visited, queue)
|| findAndAdd(curX, curY + 1, toX, toY, blockSet, visited, queue)) {
return true;
}
}
return visited.size() > maxPoints;
}
// 来到的点,(row, col)
// 要寻找的目标点toX toY
// HashSet<Long> blockSet存着不能走的格子障碍点
// HashSet<Long> visited, Queue<Long> queue 为了宽度优先遍历服务的!
// visited已经处理过的点请不要重复的放入queue
// 如果已经到达了(toX toY)
public static boolean findAndAdd(long row, long col,
int toX, int toY, HashSet<Long> blockSet,
HashSet<Long> visited, Queue<Long> queue) {
if (row < 0 || row == offset || col < 0 || col == offset) {
return false;
}
if (row == toX && col == toY) {
return true;
}
long value = row * offset + col;
if (!blockSet.contains(value) && !visited.contains(value)) {
visited.add(value);
queue.add(value);
}
return false;
}
}