코딩테스트/백준

[백준 16234번] 인구 이동

seung_ho_choi.s 2025. 5. 30. 17:03
728x90

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

 

package implement;

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

public class Impl16234 {
    static int N;

    static int L;
    static int R;

    static int[][] map;

    static int result = 0;

    // visit가 true일때 탐색 불가 왜냐하면 동시에 돌아서 데이터 정합성 깨짐 1일마다 갱신됨 대신


    // wall에서 담아서 탐색하기

    static boolean resultFlag;

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

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        L = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());
        map = new int[N][N];


        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        countDay();
        System.out.println(result);
    }

    private static void countDay() {

        while (true) {
            resultFlag = false;
            boolean[][] visit = new boolean[N][N];
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (!visit[i][j]) {
                        slove(i, j, visit);
                    }
                }
            }

            if (!resultFlag) {
                break;
            }

            result++;
        }

    }

    private static void slove(int x, int y, boolean[][] visit) {
        Queue<int[]> queue = new LinkedList<>();
        List<int[]> wall = new ArrayList<>();
        visit[x][y] = true;
        wall.add(new int[]{x, y});
        queue.add(new int[]{x, y});
        int cnt = 1;
        int sum = map[x][y];
        while (!queue.isEmpty()) {
            int[] temp = queue.poll();
            int sX = temp[0];
            int sY = temp[1];

            for (int i = 0; i < 4; i++) {
                int nextX = sX + dx[i];
                int nextY = sY + dy[i];
                if (nextX < 0 || nextX >= N || nextY < 0 || nextY >= N) {
                    continue;
                }
                if (visit[nextX][nextY]) {
                    continue;
                }
                int substance = Math.abs(map[sX][sY] - map[nextX][nextY]);
                if (substance >= L && substance <= R) {
                    resultFlag = true;
                    visit[nextX][nextY] = true;
                    cnt++;
                    sum += map[nextX][nextY];
                    queue.add(new int[]{nextX, nextY});
                    wall.add(new int[]{nextX, nextY});
                }
            }
        }

        int value = sum / cnt;

        for (int[] pos : wall) {
            map[pos[0]][pos[1]] = value;
        }

    }

}

 

핵심은 왼쪽에 벽이 있어도 다른 방향에서 벽이 없다면 해당 좌표를 wall 리스트에 넣어 계산해주면 된다는 것이다.
visit 배열은 하루마다 초기화되며, 이는 동시에 돌 때 데이터 정합성을 보장하기 위해 사용된다.

초반에 wall을 boolean 배열로 뒀더니 매번 새로 만들어야 해서 시간초과가 났다. 배열은 new boolean[N][N]로 매번 새로 할당되면서 메모리 할당 비용이 크기 때문에 시간초과가 발생한 것이다. 그래서 List로 관리해 효율성을 높였다.

문제 자체는 어렵지 않았지만, 시간이 좀 많이 걸렸다. 더 단축하고 연습해야겠다.

728x90