Find the Safest Path in a Grid
MediumArrayBinary SearchBreadth-First SearchUnion FindHeap (Priority Queue)Matrix
Solution
import { Heap } from '@algorithm/lib';
export function maximumSafenessFactor(grid: number[][]): number {
const n = grid.length;
const distances = findDistanceToThieves(grid);
const heap = new Heap<number[]>((a, b) => b[0] - a[0]);
const visited: boolean[][] = Array.from({ length: n }, () => new Array(n).fill(false));
heap.push([distances[0][0], 0, 0]);
while (!heap.isEmpty) {
const [distance, r, c] = heap.pop()!;
if (r === n - 1 && c === n - 1) {
return distance;
}
if (!visited[r][c]) {
visited[r][c] = true;
for (const [nr, nc] of adjacent(r, c, n)) {
heap.push([Math.min(distance, distances[nr][nc]), nr, nc]);
}
}
}
return -1;
}
function* adjacent(r: number, c: number, n: number) {
const directions = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0],
];
for (const [dr, dc] of directions) {
const [nr, nc] = [r + dr, c + dc];
if (0 <= nr && nr < n && 0 <= nc && nc < n) {
yield [nr, nc];
}
}
}
function findDistanceToThieves(grid: number[][]) {
const n = grid.length;
const thieves = grid
.flatMap((row, r) => row.map((_, c) => [r, c]))
.filter(([r, c]) => grid[r][c] === 1);
const visited: boolean[][] = Array.from({ length: n }, () => new Array(n).fill(false));
const distances: number[][] = Array.from({ length: n }, () => new Array(n).fill(0));
let depth = 0;
let queue = thieves;
while (0 < queue.length) {
const nextQueue = [];
for (const [r, c] of queue) {
if (visited[r][c]) continue;
visited[r][c] = true;
distances[r][c] = depth;
nextQueue.push(...adjacent(r, c, n));
}
queue = nextQueue;
depth += 1;
}
return distances;
}