반응형
문제
https://www.acmicpc.net/problem/14940
14940번: 쉬운 최단거리
지도의 크기 n과 m이 주어진다. n은 세로의 크기, m은 가로의 크기다.(2 ≤ n ≤ 1000, 2 ≤ m ≤ 1000) 다음 n개의 줄에 m개의 숫자가 주어진다. 0은 갈 수 없는 땅이고 1은 갈 수 있는 땅, 2는 목표지점이
www.acmicpc.net
풀이
class Queue {
constructor() {
this.data = [];
this.head = 0;
this.tail = 0;
}
push(item) {
this.data[this.tail++] = item;
}
pop() {
this.head++;
}
front() {
return this.data[this.head];
}
rear() {
return this.data[this.tail - 1];
}
isEmpty() {
return this.head === this.tail;
}
size() {
return Math.abs(this.head - this.tail);
}
}
const fs = require("fs");
const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const [n, ...arr] = fs.readFileSync(filePath).toString().trim().split("\n");
const [N, M] = n.split(" ").map(Number);
const dir = [
[-1, 0],
[1, 0],
[0, -1],
[0, 1],
];
const map = arr.map((row) => row.split(" ").map(Number));
const q = new Queue();
const ch = Array.from({ length: N }, () => Array(M).fill(0));
const dis = Array.from({ length: N }, () => Array(M).fill(0));
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
if (map[i][j] === 2) {
q.push([i, j]);
ch[i][j] = 1;
dis[i][j] = 0;
while (!q.isEmpty()) {
const [x, y] = q.front();
q.pop();
for (let i = 0; i < 4; i++) {
const nx = x + dir[i][0];
const ny = y + dir[i][1];
if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue;
if (map[nx][ny] === 1 && ch[nx][ny] === 0) {
dis[nx][ny] = dis[x][y] + 1;
ch[nx][ny] = 1;
q.push([nx, ny]);
}
}
}
}
}
}
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
if (map[i][j] === 1 && ch[i][j] === 0) dis[i][j] = -1;
}
}
console.log(dis.map((row) => row.join(" ")).join("\n"));
시도
처음에 아래와 같이 각 지점에서 목표 지점까지의 거리라고 문제 그대로 생각하고 2중 for문 안에서 값이 1인 경우 2까지의 거리를 저장하도록 문제를 풀었다. 답은 나왔지만 백준에서 메모리 초과가 나왔다.
const [N, M] = n.split(" ").map(Number);
const dir = [
[-1, 0],
[1, 0],
[0, -1],
[0, 1],
];
const map = arr.map((row) => row.split(" ").map(Number));
const answer = Array.from({ length: N }, () => Array(M).fill(0));
// for문에서 각 노드를 돌면서 목표지점까지 거리 출력
// 1. 1인 경우 -> 갈 수 있으면 거리 출력, 아니면 -1
// 2. 0인 경우 0 -> 그냥 리턴
const BFS = (i, j) => {
const q = new Queue();
const ch = Array.from({ length: N }, () => Array(M).fill(0));
const dis = Array.from({ length: N }, () => Array(M).fill(0));
dis[i][j] = 0;
q.push([i, j]);
ch[i][j] = 1;
while (!q.isEmpty()) {
const [x, y] = q.front();
q.pop();
for (let k = 0; k < 4; k++) {
const nx = x + dir[k][0];
const ny = y + dir[k][1];
if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue;
// 도착지
if (map[nx][ny] === 2) {
return dis[x][y] + 1;
}
if (ch[nx][ny] === 0 && map[nx][ny] === 1) {
q.push([nx, ny]);
ch[nx][ny] = 1;
dis[nx][ny] = dis[x][y] + 1;
}
}
}
return -1;
};
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
if (map[i][j] === 0 || map[i][j] === 2) continue;
if (map[i][j] === 1) answer[i][j] = BFS(i, j);
}
}
console.log(answer.map((row) => row.join(" ")).join("\n"));
해결 방법은 풀이와 같이 반대로 목적지인 2에서 값이 1인 지점까지의 거리를 구하는 것이다. 그렇게 하면 bfs를 값이 1인 지점마다 돌지 않고 한 번만 돌게 된다. 그리고 출력하기 전 값이 1이면서 방문하지 않은 지점인 경우 dis배열에서 해당 지점의 값을 -1로 변경한다.
문제를 풀기 위한 다양한 방법을 생각해보고 가장 효율적인 답을 생각하도록 해야겠다.
반응형
'Algorithm > BOJ' 카테고리의 다른 글
[알고리즘/백준/18258] 큐 2 (0) | 2023.05.25 |
---|---|
[알고리즘/백준/9012] 괄호(스택) (0) | 2023.05.25 |
[알고리즘/백준/10828] 스택(자료구조) (0) | 2023.05.24 |
[알고리즘/백준/16918] 봄버맨(BFS, Nodejs) (4) | 2023.05.23 |
[알고리즘/백준/2667] 단지 번호 붙이기 (1) | 2023.05.23 |