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

2 years ago
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;
}
}