January 29, 2023
https://www.acmicpc.net/problem/2636
처음 생각에 바깥쪽 공기와 붙어있는 치즈는 녹아야 하고, 안쪽 구멍과 붙어있는 치즈는 녹지 않아야 하기 때문에 어떻게 바깥쪽 공기와 안쪽 구멍을 구분해야 하는지 헤맸는데 생각해보니 [0, 0] 좌표는 무조건 공기이기 때문에 시작점과 이어진 곳을 공기라고 인식하고, 바로 옆에 맞닿은 치즈만 제거하면 되는 거였다.
더 이상 녹을 치즈가 없을 때까지 이하 로직을 반복한다.
- 큐에 [0, 0] 좌표를 넣는다.
큐가 비어있게 될 때까지, 꺼내면서 다음을 반복한다. (BFS 탐색)
- 현재 위치의 값이 0이면 공기이므로, 현재 위치의 상하좌우에 해당하는 위치를 큐에 넣는다.
- 현재 위치의 값이 1이면 치즈이므로, 녹이고 갯수를 기록한다.
- 진행 시간 카운트를 기록한다.
// 입력 정제
const fs = require("fs");
function getInput(caseID) {
const filePath = process.platform === "linux" ? "/dev/stdin" : `./${__dirname.split('\\').pop()}/i${caseID}.txt`;
const input = fs.readFileSync(filePath).toString().split("\n").map(item => item.trim());
input.pop();
const [height, width] = input.shift().split(" ").map(item => Number(item));
const map = [];
for (let y = 0; y < height; y++) {
map.push(input.shift().split(" ").map(item => Number(item)));
}
return [height, width, map];
}
// 문제
const [height, width, map] = getInput(1);
function isInBoundary(x, y) {
if (x < 0 || x >= width) return false;
if (y < 0 || y >= height) return false;
return true;
}
function solution() {
const queue = [];
let hourCount = 0; // 한 시간 지날 때마다 카운트
let prevMeltCount = 0; // 모두 녹기 한 시간 전에 남아있는 치즈의 갯수
let meltCount = 0; // 현재 녹는 치즈의 갯수
// 한 시간 지날때마다 가장자리의 치즈가 녹는다.
do {
let visited = Array.from({length: height}, () => Array.from({length: width}, () => 0));
meltCount = 0;
queue.push([0, 0]);
while (queue.length > 0) {
const [nowY, nowX] = queue.shift();
if (isInBoundary(nowX, nowY) && !visited[nowY][nowX]) {
visited[nowY][nowX] = 1;
// 현재 위치가 공기이면 근처 노드 BFS 탐색
if (map[nowY][nowX] === 0) {
const dx = [1, 0, -1, 0];
const dy = [0, 1, 0, -1];
for (let i = 0; i < 4; i++) {
const nextX = nowX + dx[i];
const nextY = nowY + dy[i];
queue.push([nextY, nextX]);
}
// 현재 위치가 치즈이면 녹음
} else if (map[nowY][nowX] === 1) {
meltCount++;
map[nowY][nowX] = 0;
}
}
}
if (meltCount === 0) break;
hourCount++;
prevMeltCount = meltCount;
} while (meltCount > 0);
console.log(hourCount);
console.log(prevMeltCount);
}
// 실행
solution();