[백준/JAVA] 17144번: 미세먼지 안녕!
📖 문제
17144번: 미세먼지 안녕!
미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사
www.acmicpc.net
💡 풀이 방식
• 시뮬레이션
1. 집 정보를 입력받으면서, 공기청정기 위치 cleaner도 함께 입력받는다.
2. T초 동안 아래 과정을 반복한다.
→ 1) 미세먼지 위치와 미세먼지 양을 확인해 큐에 저장한다. (❌ 미세먼지 위치만 저장❌ 나중에 격자에서 해당 칸 값 map[i][j] 받아와서 기존 배열을 바로 수정하게 되면 틀린다.)
→ 2) 모든 미세먼지가 있는 칸을 돌며 먼지를 확산시킨다. 이 때, 확산될 먼지가 없다면 = 해당 칸의 값이 5보다 작다면 패스한다.
→ 3) 공기 청정기를 작동시킨다.
┕ 위쪽 공기 청정는 반시계 방향 순환시키고, 공기 청정기에서 부는 바람은 미세먼지가 사라진 처리 (map[cleaner][1] = 0) 한다.
┕ 위쪽 공기 청정는 시계 방향 순환시키고, 공기 청정기에서 부는 바람은 미세먼지가 사라진 처리 (map[cleaner + 1][1] = 0) 한다.
💥 유의사항
- 먼지의 위치는 매번 1초마다 한 번씩 확인해줘야 한다.
- 미세먼지 확산 시 기존 배열을 바로 수정하지 않는 것 ! 큐에 (행, 열) 값만 저장하고, 확산시킬 때 map[행][열] 이렇게 기존 배열의 값을 가져와서 바로 수정하면 틀린다... (이것 땜에 2시간 날림) (참고)
- 테두리 회전 = 격자 밀 때 "당기기"의 개념으로 생각하는 것이 좋다.
- 공기청정기에서 부는 바람은 미세먼지가 없음(0) 처리를 해줘야 한다!
🔺 코드
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
import java.util.*;
import java.io.*;
public class Main {
static int[] dx = {0, -1, 0, 1};
static int[] dy = {1, 0, -1, 0};
static int R, C, T;
static int[][] map;
static int cleaner = -1; // 공기 청정기 위치
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine() ," ");
R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
T = Integer.parseInt(st.nextToken());
map = new int[R][C];
for(int i = 0 ; i < R ; i++) {
st = new StringTokenizer(br.readLine() ," ");
for(int j = 0 ; j < C ; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(cleaner == -1 && map[i][j] == -1)
cleaner = i;
}
}
while(T --> 0) {
diffuse();
work();
}
calculate();
}
// 1. 미세먼지 4방향 확산시키기
private static void diffuse() {
// 1) 미세먼지 위치 저장하기
Queue<int[]> dusts = new ArrayDeque<>();
for(int i = 0 ; i < R ; i++) {
for(int j = 0 ; j < C ; j++) {
if(map[i][j] == 0 || map[i][j] == -1) continue;
dusts.add(new int[]{i, j, map[i][j]}); // 🔔 (i,j) 만 넣고 나중에 map[i][j] 쓰려면 틀린다!!!!!!!!
}
}
// 2) 미세먼지 확산하기
while(!dusts.isEmpty()) {
int[] now = dusts.poll();
if(now[2] < 5) continue; // 🔔 확산될 먼지 없으면 패스
int cnt = 0; // 확산되는 방향 수
int dust = now[2] / 5; // 확산되는 양
for(int dir = 0 ; dir < 4 ; dir++) {
int nr = now[0] + dx[dir];
int nc = now[1] + dy[dir];
// 인접 위치에 공기청정기 있거나, 칸이 없으면 X
if(nr < 0 || nr >= R || nc < 0 || nc >= C) continue;
if(map[nr][nc] == -1) continue;
map[nr][nc] += dust;
++cnt;
}
map[now[0]][now[1]] -= dust * cnt;
}
}
// 2. 공기 청정기 작동 (= 테두리 회전)
private static void work() {
// [1] 위쪽 공청 = 반시계 방향 순환
int top = cleaner;
// 1) 아래로 당기기
for(int i = top - 1 ; i > 0 ; i--) map[i][0] = map[i-1][0];
// 2) 왼쪽으로 당기기
for(int i = 0 ; i < C - 1 ; i++) map[0][i] = map[0][i+1];
// 3) 위로 당기기
for(int i = 0 ; i < top ; i++) map[i][C-1] = map[i+1][C-1];
// 4) 오른쪽으로 당기기
for(int i = C - 1 ; i > 1 ; i--) map[top][i] = map[top][i-1];
map[top][1] = 0; // ⭐ 공기청정기에서 부는 바람은 미세먼지 X
// [2] 아래쪽 공청 = 시계 방향 순환
int down = cleaner + 1;
// 1) 위로 당기기
for(int i = down + 1 ; i < R - 1 ; i++) map[i][0] = map[i+1][0];
// 2) 왼쪽으로 당기기
for(int i = 0 ; i < C - 1 ; i++) map[R-1][i] = map[R-1][i+1];
// 3) 아래로 당기기
for(int i = R - 1 ; i > down ; i--) map[i][C-1] = map[i-1][C-1];
// 4) 오른쪽으로 당기기
for(int i = C - 1 ; i > 1 ; i--) map[down][i] = map[down][i-1];
map[down][1] = 0; // ⭐ 공기청정기에서 부는 바람은 미세먼지 X
}
private static void calculate() {
int total = 0;
for(int[] i : map) {
for(int j : i) {
if(j == -1) continue;
total += j;
}
}
System.out.println(total);
}
}
|
cs |
➕ 다른 풀이 방식
- 임시 배열에 값 만들어서 활용하셨고, while문으로 회전시키셨다. (추구미..)
[Java] 백준 17144번 미세먼지 안녕!
시뮬레이션 문제입니다. 미세먼지를 확산하고 공기청정기를 작동하는 것을 1초이며, t초 후 미세먼지의 양을 출력합니다. 미세먼지는 미세먼지/5를 4방향으로 확산합니다. (공기청정기, 벽일 경
j3sung.tistory.com
💦 어려웠던 점
- 배열 한 칸씩 회전시킬 때 당기는 개념은 인지하고 있었는데 while문 활용해서 방향 설정을 어떻게 해야할지 고민을 오래 했다. 배열 미는 문제를 다시 더 풀어봐겠다,,
- 매번 미세먼지의 위치와 값을 확인해서 리스트에 저장하고 활용할 생각을 하지 못 했다.
🧐 새로 알게 된 내용
- "동시에 확산"시킬 때는 임시 배열 만들어 활용하거나, 큐에 좌표값이랑 value까지 함께 저장해서 배열의 값을 바로 수정하지 않도록 해야겠다,,,ㅎㅎ
1회독 | 2회독 | 3회독 | 4회독 | 5회독 |
V |
(참고)
✔ 풀이 참고
[BOJ] 17144.미세먼지 안녕!(시뮬레이션).java
#. Problemhttps://www.acmicpc.net/problem/17144* The copyright in this matter is in BOJ #. Resolution Process 1. Read and understand problem 2. Redefine the problem + abstract 3. Create solution plan (select Algorithm, Data structure) 4. Prove the plan (ch
data-make.tistory.com