[BOJ 17144] 미세먼지 안녕

업데이트:

문제

  • BOJ 17144
  • 문제의 저작권은 Baekjoon Online Judge에 있습니다.

접근방식

한달전 쯤 풀었었는데 스터디를 하면서 한번 더 풀어본 문제이다.
그래서인지 쉽게 생각할 수 있었고 코드도 이전에 비해 더 간결해졌다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;


public class Main{

    static int R,C,T;
    static int[][] map;
    static int[][] copy;
    static int[] di = {-1, 0, 1, 0}; //북동남서
    static int[] dj = {0, 1, 0, -1};
    static int r; //공기청정기 윗행 좌표
    static int Ans;

    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(map[i][j]==-1 && r==0) r = i;
            }
        }//Input map

        int t = 0;
        while(++t<=T){
            //1. 확산
            spread();
            //2. 공기청정기 작동
            clean();
        }

        //출력
        for(int i=0; i<R; i++){
            for(int j=0; j<C; j++){
                if(map[i][j] == -1) continue;
                Ans += map[i][j];
            }
        }
        System.out.println(Ans);
    }

    private static void clean() {
        //1. 반시계방향: 들어가는 쪽 공백부터 => 남서북동
        for(int i=r-1; i>0; i--) map[i][0] = map[i-1][0];
        for(int j=0; j<C-1; j++) map[0][j] = map[0][j+1];
        for(int i=0; i<r; i++) map[i][C-1] = map[i+1][C-1];
        for(int j=C-1; j>1; j--) map[r][j] = map[r][j-1];
        map[r][1] = 0; //나오는쪽 0


        //2. 시계방향: 들어가는 쪽 공백부터 => 북서남동
        r++; //공기청정기 아래행
        for(int i=r+1; i<R-1; i++) map[i][0] = map[i+1][0];
        for(int j=0; j<C-1; j++) map[R-1][j] = map[R-1][j+1];
        for(int i=R-1; i>r; i--) map[i][C-1] = map[i-1][C-1];
        for(int j=C-1; j>1; j--) map[r][j] = map[r][j-1];
        map[r][1] = 0;
        r--; //다시 윗행
    }

    private static void spread() {
        copy = new int[R][C];
        copy[r][0] = -1;//공기청정기 표시
        copy[r+1][0] = -1;

        for(int i=0; i<R; i++){
            for(int j=0; j<C; j++){
                if(map[i][j]>0){ //미세먼지가 있으면
                    int cnt = 0; //확산횟수

                    for(int d=0; d<4; d++){ //4방향 탐색
                        int ni = i+di[d];
                        int nj = j+dj[d];

                        //확산할 수 있는지 체크
                        if(ni>=0 && ni<R && nj>=0 && nj<C && map[ni][nj]!=-1){
                            copy[ni][nj] += map[i][j]/5;
                            cnt++;
                        }
                    }
                    //현재 좌표에서 남은 양 계산
                    copy[i][j] += map[i][j]-(map[i][j]/5)*cnt;
                }
            }
        }//End 확산

        //copy를 map으로
        for(int i=0; i<R; i++){
            for(int j=0; j<C; j++){
                map[i][j] = copy[i][j];
            }
        }
    }
}