백준 17144 [자바] java 미세먼지 안녕!
문제 링크: https://www.acmicpc.net/problem/17144
▶ 문제
미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 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초가 지난 후 구사과 방에 남아있는 미세먼지의 양을 출력한다.
▶ 해설
문제의 길이가 상당히 길지만 천천히 하나씩 해결해 나간다면 어렵지 않은 문제입니다. 조건들을 살펴봅시다.
1. 먼지들은 상하좌우로 동시에 퍼져나가며 칸이 없거나 공기청정기가 있다면 퍼져나가지 않는다.
2. 먼지는 해당칸/5(나머지 x)로 퍼지고, 해당칸은 퍼진 것의 양만큼 줄어든다.
3. 퍼진 후 공기청정기가 작동하여 공기청정기가 차지하는 밑에 칸에는 시계방향, 위에 칸에는 반시계 방향으로 먼지들을 밀어냅니다.
4. 먼지가 공기청정기로 들어온다면 정화되고 0이 배출됩니다.
위의 조건들을 보면 일단 2차원 배열이 하나 필요합니다. map[][]이라고 하겠습니다.
먼지가 동시에 퍼져나갈 때 임시의 값을 저장할 필요가 있는 tMap이 있습니다. 그 이유는 map하나로 한다면 퍼져나가 더해진 값이 또 퍼져나가기 때문에 동시에 퍼져나갔다고 할 수 없습니다. 이 부분을 고려해서 코드를 작성하면 됩니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;
public class Main {
static int R, C, T;
static int[][] map;
static int[] up = {1, -1, 0, 0}, side = {0, 0, 1, -1};
static int airPos1, airPos2;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] s = br.readLine().split(" ");
R = Integer.parseInt(s[0]);
C = Integer.parseInt(s[1]);
T = Integer.parseInt(s[2]);
map = new int[R][C];
int num = 0;
for (int i = 0; i < R; i++) {
String[] s1 = br.readLine().split(" ");
for (int j = 0; j < C; j++) {
map[i][j] = Integer.parseInt(s1[j]);
}
}
findAir(); // 공기청정기 위치를 찾아 airPos1, airPos2에 넣어줍니다.
for (int i = 0; i < T; i++) {
solve();
}
int result = count(); // map의 배열 남아있는 먼지의 양을 계산해줍니다.
System.out.println(result + 2); // count()에서 공기청정기 값인 -1을 2번 더했으므로 2를 더해줍니다.
}
public static void findAir() {
for (int i = 0; i < R; i++) {
if (map[i][0] == -1) {
airPos1 = i;
airPos2 = i + 1;
break;
}
}
}
public static void solve() {
map=dustSimulation(); // 먼지가 퍼져나가는 것을 구하는 함수
airSimulation(); // 공기청정기로 먼지가 들어오며 나가는 것을 구하는 함수
}
public static void airSimulation() {
int top = airPos1; // 공기청정기 윗 부분좌표며, 반시계 방향으로 진행
for (int x = top - 1; x > 0; x--) {
map[x][0] = map[x - 1][0];
}
for (int y = 0; y < C - 1; y++) {
map[0][y] = map[0][y + 1];
}
for (int x = 0; x < top; x++) {
map[x][C - 1] = map[x + 1][C - 1];
}
for (int y = C - 1; y > 1; y--) {
map[top][y] = map[top][y - 1];
}
map[top][1] = 0; // 공기청정기로 나가는 곳이므로 먼지는 0이다.
int bottom = airPos2; // 공기청정기 밑 부분좌표며, 시계방향으로 진행
for (int x = bottom + 1; x < R - 1; x++) {
map[x][0] = map[x + 1][0];
}
for (int y = 0; y < C - 1; y++) {
map[R - 1][y] = map[R - 1][y + 1];
}
for (int x = R - 1; x > bottom; x--) {
map[x][C - 1] = map[x - 1][C - 1];
}
for (int y = C - 1; y > 1; y--) {
map[bottom][y] = map[bottom][y - 1];
}
map[bottom][1] = 0; // 공기청정기로 나가는 곳이므로 먼지는 0이다.
}
public static int[][] dustSimulation() {
int[][] tMap = new int[50][50];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (map[i][j] == -1) {
tMap[i][j] = -1;
continue;
}
tMap[i][j] += map[i][j];
for (int k = 0; k < 4; k++) {
int nx = j + side[k];
int ny = i + up[k];
if (ny < 0 || ny >= R || nx < 0 || nx >= C) continue;
if (map[ny][nx] == -1) continue;
tMap[ny][nx] += (map[i][j] / 5);
tMap[i][j] -= (map[i][j] / 5);
}
}
}
return tMap;
}
public static int count() {
int temp = 0;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
temp += map[i][j];
}
}
return temp;
}
}
'Alogorithm > simulation' 카테고리의 다른 글
백준 16235[자바] java 나무 재테크 (0) | 2022.04.11 |
---|---|
백준 15685 [자바] java 드래곤 커브 (0) | 2022.02.05 |
백준 JAVA 14891번 톱니바퀴 (0) | 2021.12.04 |
댓글
이 글 공유하기
다른 글
-
백준 16235[자바] java 나무 재테크
백준 16235[자바] java 나무 재테크
2022.04.11 -
백준 15685 [자바] java 드래곤 커브
백준 15685 [자바] java 드래곤 커브
2022.02.05 -
백준 JAVA 14891번 톱니바퀴
백준 JAVA 14891번 톱니바퀴
2021.12.04