알고리즘/구현
[백준 17144번] 미세먼지 안녕!
moongi
2025. 7. 3. 15:03
728x90
반응형
https://www.acmicpc.net/problem/17144
문제 유형
- 시뮬레이션
- 구현
문제 난이도
Gold4
문제 분석
해당 문제는 전형적인 시뮬레이션, 구현 문제이다. 해당 문제는 삼성 SW 역량 테스트 기출 문제이므로 가볍게 풀어보면 좋을 것 같다.
총 두 가지의 메소드로 구분해서 구현하면 된다.
1. 미세먼지 확산
- 확산될 미세먼지들을 누적해서 갱신하기 위해 2차원 임시 배열을 생성한다.
- 0과 -1이 아닌 위치에 대하여 4방향에 대하여 벽이 아닌 구역들에 대해 확산이 가능하다고 가정하고, 현재 미세먼지의 양 / 5 만큼을 각각의 위치에 갱신하고, 현재 위치는 미세먼지를 확산시켰으므로 확산 시킨 양만큼을 감소시켜서 배열을 갱신시켜준다.
- 갱신하는 과정에서 공기청정기의 위치에 -1을 넣어주는 걸 까먹지 않는다.
2. 공기청정기 작동
- 위쪽 공기 청정기와 아랫쪽 공기청정기를 각각 나누고, 반시계방향과 시계방향에 대해 모든 자리들을 한 칸씩 이동시켜준다. 해당 조건에서 주의할 점은 이동하는 방향의 반대 방향에 대하여 반복문을 순회하여야, 값이 누락되는 것 없이 모든 값들을 처리해줄 수 있다.
- 반복문에서 시작 위치와 마지막 종료 위치를 항상 생각하면서 실수하지 않도록 한다.
전체 코드
package _250703;
import java.util.*;
import java.io.*;
/**
*packageName : _250703
* fileName : BOJ_G4_17144_미세먼지안녕
* author : moongi
* date : 7/3/25
* description :
*/
public class BOJ_G4_17144_미세먼지안녕 {
static int R, C, T;
static int[][] board;
static int[] conditioner;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
T = Integer.parseInt(st.nextToken());
board = new int[R][C];
conditioner = new int[2];
int idx = 0;
for (int i = 0; i < R; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < C; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
// 공기 청정기의 위치 저장
if (board[i][j] == -1) {
conditioner[idx++] = i;
}
}
}
int time = 0;
while(time < T) {
moveDust();
moveAir(conditioner);
// 1초 경과
time++;
}
int ans = 0;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
ans += board[i][j];
}
}
sb.append(ans + 2);
System.out.println(sb);
}
static void moveDust() {
int[][] tmp = new int[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
int sum = 0;
int part = board[i][j] / 5;
for (int d = 0; d < 4; d++) {
int nx = i + dx[d];
int ny = j + dy[d];
if (!isValid(nx, ny)) continue;
tmp[nx][ny] += part;
sum += part;
}
tmp[i][j] += board[i][j] - sum;
}
}
// 먼지 확산 이후
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
board[i][j] = tmp[i][j];
}
}
// 공기 청정기 위치
board[conditioner[0]][0] = -1;
board[conditioner[1]][0] = -1;
}
static boolean isValid(int x, int y) {
if (x >= R || x < 0 || y >= C || y < 0 || board[x][y] == -1) return false;
return true;
}
static void moveAir(int[] conditioner) {
// 모두 한 칸씩 이동하며, 공기 청정기 위치에 도착 시, 해당 먼지는 제거
// 위쪽 공기 청정기: 반시계 방향
for (int i = conditioner[0] - 1; i >= 1; i--) {
board[i][0] = board[i - 1][0];
}
for (int i = 0; i < C - 1; i++) {
board[0][i] = board[0][i + 1];
}
for (int i = 0; i < conditioner[0]; i++) {
board[i][C - 1] = board[i + 1][C - 1];
}
for (int i = C - 1; i > 1; i--) {
board[conditioner[0]][i] = board[conditioner[0]][i - 1];
}
board[conditioner[0]][1] = 0;
// 아래쪽 공기 청정기: 시계 방향
for (int i = conditioner[1] + 1; i < R - 1; i++) {
board[i][0] = board[i + 1][0];
}
for (int i = 0; i < C - 1; i++) {
board[R - 1][i] = board[R - 1][i + 1];
}
for (int i = R-1; i > conditioner[1]; i--) {
board[i][C - 1] = board[i - 1][C - 1];
}
for (int i = C - 1; i > 1; i--) {
board[conditioner[1]][i] = board[conditioner[1]][i - 1];
}
board[conditioner[1]][1] = 0;
}
}
728x90
반응형