보물 지도
Lv. 3
Solution
export function treasureMap(n: number, m: number, hole: number[][]): number {
const directions = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0],
];
const distance = new Array(n)
.fill(null)
.map(() => new Array(m).fill(null).map(() => [Infinity, Infinity]));
for (const [a, b] of hole) {
distance[a - 1][b - 1][0] = -1;
distance[a - 1][b - 1][1] = -1;
}
distance[0][0][0] = 0;
distance[0][0][1] = 0;
function isMovable(y: number, x: number) {
return 0 <= y && y < n && 0 <= x && x < m;
}
const queue = [[0, 0, 1]];
while (0 < queue.length) {
const peek = queue.shift();
if (!peek) {
continue;
}
const [cy, cx, canSkip] = peek;
const nd = distance[cy][cx][canSkip] + 1;
for (const [dy, dx] of directions) {
const [ny, nx] = [cy + dy, cx + dx];
if (isMovable(ny, nx) && nd < distance[ny][nx][canSkip]) {
distance[ny][nx][canSkip] = nd;
queue.push([ny, nx, canSkip]);
}
}
if (!canSkip) {
continue;
}
for (const [dy, dx] of directions) {
const [ny, nx] = [cy + 2 * dy, cx + 2 * dx];
if (isMovable(ny, nx) && nd < distance[ny][nx][0]) {
distance[ny][nx][0] = nd;
queue.push([ny, nx, 0]);
}
}
}
const minDistance = Math.min(...distance[n - 1][m - 1]);
return minDistance === Infinity ? -1 : minDistance;
}