티스토리 뷰

문제 - (주소)

전형적인 시뮬레이션 문제였다.

구현하라는대로 구현하면 됐다. 단 구현시 알아두면 좋은 것들이 있는데 그것을 소개하겠다.

 

1. 방향 조회하기

static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};

위, 오른, 아래, 위 방향으로 이동하기 위해 초기화한 배열이다.

어떻게 사용하냐면

map이라는 이차원 배열이 있다고 할 때,

for (int d = 0; d <= 3; d++) {
	int moveX = i + dx[d];
	int moveY = j + dy[d];
    map[moveX][moveY];
}

이렇게 하면 d가 0~3까지 4번동안 dx, dy를 통해 map을 위, 오른, 아래, 위 방향으로 조회가 가능하다.

 

2. 조회하는 방향 응용하기

문제에서 공기청정기 바람의 이동방향이 있었는데, 나는 앞서 언급한 방향 조회하기를 응용해봤다.

위쪽의 공기청정기 바람은 오른 -> 위 -> 왼 -> 아래 방향으로 흐르고

아래쪽의 공기청정기 바람은 오른 -> 아래 -> 왼 -> 위 방향으로 흐른다.

위,오른,아래,왼이 차례로 dx, dy의 0,1,2,3 인덱스임을 이용해서 배열을 선언해서 순회하도록 구현했다.

static int[] upSideDir = {1, 0, 3, 2};
static int[] downSideDir = {1, 2, 3, 0};

for (int i = 0; i <= 3; i++) {
	upSideAirPosX += dx[upSideDir[i]];
    upSideAirPosY += dy[upSideDir[i]];
    downSideAirPosX += dx[downSideDir[i]];
    downSideAirPosY += dy[downSideDir[i]];
}

 


📌주의할 점

  • 헷갈릴 수 있으므로 손으로 그려보면서 풀어보는 것을 추천한다
  • temp 배열을 사용한다면, 반복문마다 제대로 map을 업데이트 해줬는지 반드시 확인한다.

😅실수

  • 위쪽 공기청정기와 아래쪽 공기청정기의 바람 이동방향 로직을 구현하는 것이 비슷해서 복.붙을 했다면 수정되야 할 부분들이 정확히 수정되었는지 섬세하게 확인할 필요가 있다... 여기서 실수하면 원인 찾기가 더 힘들어진다 ㅠㅠ 디버깅을 돌린다는 것 자체가 시간에 부담됨
  • 문제를 잘 보고 문제 그대로 구현할 때, 기존에 있던 값에 더해주는 것인지 초기화하는 것인지 주의깊게 보고 코딩하자

 

오늘의 주인공
오늘의 주인공2


코드

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

/**
 * 1시간 30분
 */
public class Dust {
    static int r;
    static int c;
    static int t;
    static int[][] map;
    static int[] airCleanerUpSide;
    static int[] airCleanerDownSide;
    static int answer = 0;
    static int[] dx = {-1, 0, 1, 0}; // 위, 오른, 아래, 위 방향
    static int[] dy = {0, 1, 0, -1}; // 위, 오른, 아래, 위 방향
    static int[] upSideDir = {1, 0, 3, 2};
    static int[] downSideDir = {1, 2, 3, 0};

    static void simulate() {
        int time = 0;
        while (time != t) {
            int[][] temp = new int[r][c]; // 이 시간대에 퍼질 미세먼지 구하기

            // 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
            for (int i = 0; i < r; i++) {
                for (int j = 0; j < c; j++) {
                    if (map[i][j] == 0) continue;
                    // 현재 i,j에서 4방향 확산기키기
                    int currentPosDust = map[i][j];
                    int effectDust = currentPosDust / 5;

                    // 확산될 방향 찾아서 값 넣고 갯수 세기
                    int effectArea = 0; // 확산된 방향 수
                    for (int d = 0; d <= 3; d++) {
                        int moveX = i + dx[d];
                        int moveY = j + dy[d];
                        if (!(moveX < 0 || moveY < 0 || moveX >= r || moveY >= c || map[moveX][moveY] == -1)) {
                            temp[moveX][moveY] += effectDust;
                            effectArea++;
                        }
                    }
                    // 남은 미세먼지양 적용
                    temp[i][j] += /*실수*/ currentPosDust - ((currentPosDust / 5) * effectArea);
                }
            }
            // 확산된 결과 temp로 map 업데이트
            temp[airCleanerUpSide[0]][airCleanerUpSide[1]] = -1;
            temp[airCleanerDownSide[0]][airCleanerDownSide[1]] = -1;
            map = temp;

            // 공기청정기가 작동한다.
            int upSideAirPosX = airCleanerUpSide[0];
            int upSideAirPosY = airCleanerUpSide[1];
            int downSideAirPosX = airCleanerDownSide[0];
            int downSideAirPosY = airCleanerDownSide[1];
            int[][] airTemp = new int[r][c];

            int preUpDust = 0;
            int preDownDust = 0;
            for (int i = 0; i <= 3; i++) { // 공기청정기 4가지 방향으로 이동함
                // 위쪽 공기청정기 i번째 방향으로 계속 이동
                while (true) {
                    upSideAirPosX += dx[upSideDir[i]];
                    upSideAirPosY += dy[upSideDir[i]];
                    if (upSideAirPosX < 0 || upSideAirPosY < 0 || upSideAirPosX >= r || upSideAirPosY >= c || map[upSideAirPosX][upSideAirPosY] == -1) {
                        upSideAirPosX -= dx[upSideDir[i]]; // 이전위치로 돌아가기
                        upSideAirPosY -= dy[upSideDir[i]];
                        break;
                    }
                    airTemp[upSideAirPosX][upSideAirPosY] = preUpDust;
                    preUpDust = map[upSideAirPosX][upSideAirPosY];
                }

                // 아래쪽 공기청정기 i번째 방향으로 계속 이동
                /* 위에서 이미 구현한 것과 비슷하다고 밑에 복붙할거면
                * 바꿔야할 값들 신중하게 보고 바꾸자... 여기서 실수로 시간 많이 뺏어먹음 */
                while (true) {
                    downSideAirPosX += dx[downSideDir[i]];
                    downSideAirPosY += dy[downSideDir[i]];
                    if (downSideAirPosX < 0 || downSideAirPosY < 0 || downSideAirPosX >= r || downSideAirPosY >= c || map[downSideAirPosX][downSideAirPosY] == -1) {
                        downSideAirPosX -= dx[downSideDir[i]]; // 이전위치로 돌아가기
                        downSideAirPosY -= dy[downSideDir[i]];
                        break;
                    }
                    airTemp[downSideAirPosX][downSideAirPosY] = preDownDust;
                    preDownDust = map[downSideAirPosX][downSideAirPosY];
                }
            }

            // 바람으로 바뀐 모양으로 map 업데이트
            for (int i = 0; i < r; i++) {
                if (i == 0 || i == r - 1 || i == airCleanerUpSide[0] || i == airCleanerDownSide[0]) continue;
                for (int j = 0; j < c; j++) {
                    if (j == 0 || j == c - 1 ) continue;
                    airTemp[i][j] = map[i][j];
                }
            }
            airTemp[airCleanerUpSide[0]][airCleanerUpSide[1]] = -1;
            airTemp[airCleanerDownSide[0]][airCleanerDownSide[1]] = -1;
            map = airTemp;

            time++;
        }

        for (int[] m : map) {
            for (int _m : m) {
                if (_m == -1) continue;
                answer += _m;
            }
        }
    }

    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)
                    if (airCleanerUpSide == null) airCleanerUpSide = new int[]{i, j};
                    else airCleanerDownSide = new int[]{i, j};
            }
        }

        simulate();
        System.out.println(answer);
    }
}
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함