문제 풀이/백준

[백준] 17144번. 미세먼지 안녕!(JAVA)

27200 2025. 1. 13. 20:53

문제

https://www.acmicpc.net/problem/17144


풀이(34분)

import java.util.*;
import java.io.*;

public class Main {
    static int r, c, t;
    static int[][] arr;
    static Point upPoint, downPoint;
    static int[][] direction = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        r = Integer.parseInt(st.nextToken());
        c = Integer.parseInt(st.nextToken());
        t = Integer.parseInt(st.nextToken());
        arr = new int[r][c];

        int cnt = 1;
        for (int i = 0; i < r; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < c; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
                if (arr[i][j] == -1) {
                    if (cnt == 1) {
                        upPoint = new Point(i, j);
                        cnt++;
                    } else {
                        downPoint = new Point(i, j);
                    }
                }
            }
        }

        for (int i = 0; i < t; i++) {
            arr = diffusion();
            airPurifier();
        }

        int answer = 0;
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (arr[i][j] > 0) {
                    answer += arr[i][j];
                }
            }
        }

        System.out.println(answer);
    }

    public static void airPurifier() {
        upPurifier();
        downPurifier();
        // 공기청정기 위치는 항상 -1로 설정
        arr[upPoint.x][upPoint.y] = -1;
        arr[downPoint.x][downPoint.y] = -1;
    }

    public static void upPurifier() {
        int x = upPoint.x;

        // 위쪽 공기청정기: 반시계 방향
        for (int i = x - 1; i > 0; i--) arr[i][0] = arr[i - 1][0];  // 아래로 이동
        for (int i = 0; i < c - 1; i++) arr[0][i] = arr[0][i + 1];  // 왼쪽으로 이동
        for (int i = 0; i < x; i++) arr[i][c - 1] = arr[i + 1][c - 1];  // 위로 이동
        for (int i = c - 1; i > 1; i--) arr[x][i] = arr[x][i - 1];  // 오른쪽으로 이동

        arr[x][1] = 0; // 공기청정기 옆
    }

    public static void downPurifier() {
        int x = downPoint.x;

        // 아래쪽 공기청정기: 시계 방향
        for (int i = x + 1; i < r - 1; i++) arr[i][0] = arr[i + 1][0];  // 위로 이동
        for (int i = 0; i < c - 1; i++) arr[r - 1][i] = arr[r - 1][i + 1];  // 왼쪽으로 이동
        for (int i = r - 1; i > x; i--) arr[i][c - 1] = arr[i - 1][c - 1];  // 아래로 이동
        for (int i = c - 1; i > 1; i--) arr[x][i] = arr[x][i - 1];  // 오른쪽으로 이동

        arr[x][1] = 0; // 공기청정기 옆
    }

    public static int[][] diffusion() {
        int[][] tempArr = new int[r][c];

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (arr[i][j] > 0) {
                    int origin = arr[i][j];
                    int diffusionDust = origin / 5;

                    for (int k = 0; k < 4; k++) {
                        int tempR = i + direction[k][0];
                        int tempC = j + direction[k][1];

                        if (tempR >= 0 && tempR < r && tempC >= 0 && tempC < c && arr[tempR][tempC] != -1) {
                            tempArr[tempR][tempC] += diffusionDust;
                            origin -= diffusionDust;
                        }
                    }
                    tempArr[i][j] += origin;
                }
            }
        }

        return tempArr;
    }

    public static class Point {
        int x, y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}

 

별다른 알고리즘을 사용하지 않는 빡구현 문제라고 생각한다.

 

문제 설명과 풀이가 모두 간단하지만 실제 풀이는 생각보다 단순하다.

 

1. 확산을 먼저 진행한다.

이때 원본 배열을 둔 채로 임시 배열을 두어 원본 배열에 영향을 끼치지 않고 확산을 진행한 뒤에 다시 복사해서 넣는다. -> 이렇게 하는 이유는 한 칸씩 순서대로 확산을 진행할 경우, 이미 확산된 것이 영향을 끼칠 수 있기 때문이다.

1-1. 확산을 진행할 때 벽과 공기 청정기 등 진행이 되지 못하는 것을 고려하여 확산을 진행한다. 

 

2. 윗 순환과 아랫 순환을 별도로 메서드로 분리하여 진행한다.

2-1. 공기 청정기로 들어오는 것부터 생각하여 순서에 맞게 옮겨가며 0을 대입시켜 마무리해 준다.

 

3. 최종적으로 값을 측정한다.

 

말 그대로 구현 문제이다 보니 풀이가 어렵다기보다는 직접 코드로 작성하며 인덱스와 반복문 등을 맞추는 작업이 더욱 어려운 것 같다!