본문 바로가기

알고리즘/백준

[17144번] 미세먼지 안녕! (C++, 삼성코딩테스트)

문제

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사과는 뛰어난 코딩 실력을 이용해 각 칸 (r, c)에 있는 미세먼지의 양을 실시간으로 모니터링하는 시스템을 개발했다. (r, c)는 r행 c열을 의미한다.

공기청정기는 항상 왼쪽 열에 설치되어 있고, 크기는 두 행을 차지한다. 공기청정기가 설치되어 있지 않은 칸에는 미세먼지가 있고, (r, c)에 있는 미세먼지의 양은 Ar,c이다.

1초 동안 아래 적힌 일이 순서대로 일어난다.

  1. 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
    • (r, c)에 있는 미세먼지는 인접한 네 방향으로 확산된다.
    • 인접한 방향에 공기청정기가 있거나, 칸이 없으면 그 방향으로는 확산이 일어나지 않는다.
    • 확산되는 양은 Ar,c/5이고 소수점은 버린다.
    • (r, c)에 남은 미세먼지의 양은 Ar,c - (Ar,c/5)×(확산된 방향의 개수) 이다.
  2. 공기청정기가 작동한다.
    • 공기청정기에서는 바람이 나온다.
    • 위쪽 공기청정기의 바람은 반시계방향으로 순환하고, 아래쪽 공기청정기의 바람은 시계방향으로 순환한다.
    • 바람이 불면 미세먼지가 바람의 방향대로 모두 한 칸씩 이동한다.
    • 공기청정기에서 부는 바람은 미세먼지가 없는 바람이고, 공기청정기로 들어간 미세먼지는 모두 정화된다.

다음은 확산의 예시이다.

왼쪽과 오른쪽에 칸이 없기 때문에, 두 방향으로만 확산이 일어났다.

인접한 네 방향으로 모두 확산이 일어난다.

공기청정기가 있는 칸으로는 확산이 일어나지 않는다.

공기청정기의 바람은 다음과 같은 방향으로 순환한다.

방의 정보가 주어졌을 때, T초가 지난 후 구사과의 방에 남아있는 미세먼지의 양을 구해보자.

 

문제접근법.

1. 기존 먼지들의 양이 저장된 배열의 정보가 유지되어야 한다. 연산을 위해서 추가적인 배열이 한 개 더 정의되어야 한다.

2. 먼지가 이동하는 경로를 보면, 공기청정기로 들어가는 원소를 제거하고 이동시키면 된다.

 

 문제 자체는 어렵지 않다. 생각의 과정을 코드로 그대로 옮기는 것이 중요하다. 이 문제에서 필요한 사전 지식은 딱히 없어보인다. 연산을 위한 배열이 왜 필요한지만 이해한다면, 비슷한 문제를 손쉽게 해결할 수 있을 것이다.

 

해설 코드(C++)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
 
int op[5][2= { {}, {0,1}, {1,0},{0,-1}, {-1,0} };
int map[51][51];
int add[51][51];
int R, C, T;
int device_r1 = 0, device_r2 = 0;
int result = 0;
 
typedef struct dust {
    int r, c, amount;
    dust(int _r, int _c, int _a) :r(_r), c(_c), amount(_a) {};
}dust;
 
void spread(int r, int c) {
    int am_sp_ds = map[r][c] / 5;
 
    // Checks mve
    for (int i = 1; i <= 4; i++) {
        int n_r = r + op[i][0];
        int n_c = c + op[i][1];
 
        if (n_r < 1 || n_c < 1 || n_r > R || n_c > C || map[n_r][n_c] == -1)
            continue;
 
        map[r][c] -= am_sp_ds;
        add[n_r][n_c] += am_sp_ds;
    }
 
    return;
}
 
int main(void) {
    //freopen("input.txt", "r", stdin);
    cin >> R >> C >> T;
    for (int i = 1; i <= R; i++) {
        for (int j = 1; j <= C; j++) {
            cin >> map[i][j];
            // Remember Device r1 & r2
            if (map[i][j] == -1) {
                if (device_r1 == 0)
                    device_r1 = i;
                else
                    device_r2 = i;
            }
        }
    }
 
    for (int t = 1; t <= T; t++) {
        // Initailize add 2D array and result
        memset(add, 0sizeof(add));
        result = 0;
 
        // Spread Dust
        for (int r = 1; r <= R; r++) {
            for (int c = 1; c <= C; c++) {
                if (map[r][c] == -1 || map[r][c] == 0)
                    continue;
                spread(r, c);
            }
        }
 
        // UPDATE MAP
        for (int r = 1; r <= R; r++) {
            for (int c = 1; c <= C; c++) {
                map[r][c] += add[r][c];
                if (map[r][c] == -1)
                    continue;
                result += map[r][c];
            }
        }
 
        // AirConditioner UPPER
        result -= map[device_r1 - 1][1];
        for (int r = device_r1 - 1; r >= 2; r--) {
            map[r][1= map[r - 1][1];
        }
        for (int c = 2; c <= C; c++) {
            map[1][c - 1= map[1][c];
        }
        for (int r = 2; r <= device_r1; r++) {
            map[r - 1][C] = map[r][C];
        }
        for (int c = C; c >= 3; c--) {
            map[device_r1][c] = map[device_r1][c - 1];
        }
        map[device_r1][2= 0;
 
        // AirConditioner LOWER
        result -= map[device_r2 + 1][1];
        for (int r = device_r2 + 1; r <= R - 1; r++) {
            map[r][1= map[r + 1][1];
        }
        for (int c = 2; c <= C; c++) {
            map[R][c - 1= map[R][c];
        }
        for (int r = R; r >= device_r2 + 1; r--) {
            map[r][C] = map[r - 1][C];
        }
        for (int c = C; c >= 3; c--) {
            map[device_r2][c] = map[device_r2][c - 1];
        }
        map[device_r2][2= 0;
    }
 
    cout << result << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter