알고리즘/구현

[백준 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
반응형