문제 난이도 | 유형 |
🥇골드 4티어 | 시뮬레이션, 구현 |
문제
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞힌 사람 | 정답 비율 |
1 초 | 512 MB | 26125 | 14224 | 9548 | 53.674% |
미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1 ×1 크기의 칸으로 나눴다. 구사과는 뛰어난 코딩 실력을 이용해 각 칸 (r, c)에 있는 미세먼지의 양을 실시간으로 모니터링하는 시스템을 개발했다. (r, c)는 r행 c열을 의미한다.
공기청정기는 항상 1번 열에 설치되어 있고, 크기는 두 행을 차지한다. 공기청정기가 설치되어 있지 않은 칸에는 미세먼지가 있고, (r, c)에 있는 미세먼지의 양은 Ar,c이다.
1초 동안 아래 적힌 일이 순서대로 일어난다.
- 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
- (r, c)에 있는 미세먼지는 인접한 네 방향으로 확산된다.
- 인접한 방향에 공기청정기가 있거나, 칸이 없으면 그 방향으로는 확산이 일어나지 않는다.
- 확산되는 양은 Ar,c/5이고 소수점은 버린다.
- (r, c)에 남은 미세먼지의 양은 Ar,c - (Ar,c/5)×(확산된 방향의 개수) 이다.
- 공기청정기가 작동한다.
- 공기청정기에서는 바람이 나온다.
- 위쪽 공기청정기의 바람은 반시계방향으로 순환하고, 아래쪽 공기청정기의 바람은 시계방향으로 순환한다.
- 바람이 불면 미세먼지가 바람의 방향대로 모두 한 칸씩 이동한다.
- 공기청정기에서 부는 바람은 미세먼지가 없는 바람이고, 공기청정기로 들어간 미세먼지는 모두 정화된다.
다음은 확산의 예시이다.
왼쪽과 오른쪽에 칸이 없기 때문에, 두 방향으로만 확산이 일어났다.
공기청정기가 있는 칸으로는 확산이 일어나지 않는다.
공기청정기의 바람은 다음과 같은 방향으로 순환한다.
방의 정보가 주어졌을 때, T초가 지난 후 구사과의 방에 남아있는 미세먼지의 양을 구해보자.
입력
첫째 줄에 R, C, T (6 ≤ R, C ≤ 50, 1 ≤ T ≤ 1,000) 가 주어진다.
둘째 줄부터 R개의 줄에 Ar,c (-1 ≤ Ar,c ≤ 1,000)가 주어진다. 공기청정기가 설치된 곳은 Ar,c가 -1이고, 나머지 값은 미세먼지의 양이다. -1은 2번 위아래로 붙어져 있고, 가장 윗 행, 아랫 행과 두 칸이상 떨어져 있다.
출력
첫째 줄에 T초가 지난 후 구사과 방에 남아있는 미세먼지의 양을 출력한다.
예제 입력
7 8 1
0 0 0 0 0 0 0 9
0 0 0 0 3 0 0 8
-1 0 5 0 0 0 22 0
-1 8 0 0 0 0 0 0
0 0 0 0 0 10 43 0
0 0 5 0 15 0 0 0
0 0 40 0 0 0 20 0
예제 출력
188
풀이
단순 구현 문제이다. 확산하는 부분과 순환하는 부분을 T 만큼 반복한 후 모든 합을 구하면 된다. R x C의 맵이 최대 300이므로 최적화는 따로 고려하지 않았다. 이 문제에서 가장 유의해야 할 부분은 확산은 동시에 일어난다는 것이다. 만약 순차적으로 미세먼지를 확산시킨다면 이전의 결과가 다음 확산에 영향을 미친다. 그렇게 되면 순서에 따라서 확산의 결과가 다르다. 이 부분만 잘 캐치한다면 나머지는 난해하지 않게 풀 수 있다. 나는 확산해야 하는 모든 좌표와 새로운 값을 미리 commits 배열에 저장한 후에 동시에 반영했다. 순환의 경우에는 미리 경로를 저장해 놓고 cycle 함수 내부에서 이전 값을 다음 값에 대입시키는 로직을 구현했다. 단순 구현이라 코드가 매우 길다.
코드
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let input = [];
rl.on("line", function (line) {
input.push(line);
}).on("close", function () {
const [R, C, T] = input.shift().split(" ").map(Number);
const map = input.map((v) => v.split(" ").map(Number));
solution(map, R, C, T);
process.exit();
});
function diffusion(finedust, map, R, C) {
const dx = [0, 0, -1, 1];
const dy = [-1, 1, 0, 0];
const commits = [];
while (finedust.length !== 0) {
const [x, y] = finedust.pop();
const target = []; //확산될 공간 좌표
for (let i = 0; i < 4; i++) {
const nx = x + dx[i];
const ny = y + dy[i];
if (nx < 0 || ny < 0 || nx >= R || ny >= C) continue;
if (map[nx][ny] === -1) continue;
target.push([nx, ny]);
}
for (const [i, j] of target) {
commits.push([i, j, Math.floor(map[x][y] / 5), false]);
}
commits.push([x, y, Math.floor(map[x][y] / 5) * target.length, true]);
}
for ([x, y, newValue, op] of commits) {
if (op) {
map[x][y] -= newValue;
} else map[x][y] += newValue;
}
}
function getPath([x, y], map, R, C, directions, isFirst) {
const alpha = {
plus: 1,
minus: -1,
};
let min;
if (isFirst) {
R = x;
min = 0;
} else {
min = x;
R -= 1;
}
C -= 1;
y += 1;
let isVertical = false;
let index = 0;
let nowDir = directions[index];
const returnValue = [];
while (true) {
returnValue.push([x, y]);
if (map[x][y] === -1) break;
if (
(isVertical && (x === min || x === R)) ||
(!isVertical && (y === 0 || y === C))
) {
nowDir = directions[++index];
isVertical = !isVertical;
if (isVertical) x += alpha[nowDir];
else y += alpha[nowDir];
continue;
}
if (isVertical) x += alpha[nowDir];
else y += alpha[nowDir];
}
return returnValue;
}
function cycle(targetPos, map) {
for (const targets of targetPos) {
let prev = 0;
for (const [x, y] of targets) {
if (map[x][y] === -1) break;
let temp = map[x][y];
map[x][y] = prev;
prev = temp;
}
}
}
function getFinedust(map, R, C) {
const finedust = [];
for (let i = 0; i < R; i++) {
for (let j = 0; j < C; j++) {
if (map[i][j] > 0) finedust.push([i, j]);
}
}
return finedust;
}
function solution(map, R, C, T) {
const clockwise = ["plus", "plus", "minus", "minus"];
const counterclockwise = ["plus", "minus", "minus", "plus"];
const pathPos = [];
const machinePos = [];
let finedust = [];
for (let i = 0; i < R; i++) {
for (let j = 0; j < C; j++) {
if (map[i][j] > 0) finedust.push([i, j]);
else if (map[i][j] === -1) machinePos.push([i, j]);
}
}
pathPos.push(getPath(machinePos[0], map, R, C, counterclockwise, true));
pathPos.push(getPath(machinePos[1], map, R, C, clockwise, false));
for (let i = 0; i < T; i++) {
diffusion(finedust, map, R, C);
cycle(pathPos, map);
finedust = getFinedust(map, R, C);
}
console.log(map.flat().reduce((acc, v) => acc + v, 2));
}
'CS > 알고리즘' 카테고리의 다른 글
[백준 #1806] 부분합, 자바스크립트 풀이 (0) | 2022.10.11 |
---|---|
[백준 #1916] 최소비용 구하기, 자바스크립트 풀이 (0) | 2022.10.08 |
[백준 #7576] 토마토, 자바스크립트 풀이 (1) | 2022.10.08 |
[백준 #3197] 백조의 호수, 자바스크립트 풀이 (0) | 2022.10.04 |
[백준 #1197] 최소 스패닝 트리, 자바스크립트 풀이 (0) | 2022.09.30 |