Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
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
Archives
Today
Total
관리 메뉴

hwooo

BOJ (Java) 16234번: 인구 이동 본문

Study/Algorithm

BOJ (Java) 16234번: 인구 이동

hwooo 2025. 7. 3. 13:13

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


풀이

bfs로 탐색하며 인구 수의 차이가 주어진 조건 내에 들어가는 나라들끼리 묶은 후, 인구 수를 재배치했다.

 

각 나라가 어떤 연합인지 저장하는 배열(union)과, 각 연합이 생겼을 때 나라 별 인구 수 (총 인구 수 / 연합 나라 수)를 저장할 맵(map) 하나를 만든다.

bfs로 탐색하며 각 나라 별로 연합을 결정(groupNum)하여 배열(union)에 저장한 후, 연합의 총 인구 수(sum)와 나라 수(cnt)를 구했다.

이를 토대로 연합 별 인구 수(sum / cnt)를 구한 후 맵(groupNum, sum/cnt) 에 저장하였고, 인구를 이동(movePeople)시켰다.

이 때 인구 수가 변경되는 나라가 하나도 없다면(isMoved) 탐색을 종료한 후, 이동에 걸린 총 일자를 반환한다.


Java 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;

public class Main {
    private static int N, L, R;
    private static int[][] A, union;
    private static Map<Integer, Integer> map = new HashMap<>();
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        String[] inputs = bf.readLine().split(" ");
        N = Integer.parseInt(inputs[0]);
        L = Integer.parseInt(inputs[1]);
        R = Integer.parseInt(inputs[2]);

        A = new int[N][N];
        union = new int[N][N];

        for (int i = 0; i < N; i++) {
            inputs = bf.readLine().split(" ");
            for (int j = 0; j < N; j++) {
                A[i][j] = Integer.parseInt(inputs[j]);
            }
        }

        int cnt = 0;
        while (true) {
            // init
            for (int i = 0; i < N; i++) {
                Arrays.fill(union[i], 0);
            }
            map.clear();
            
            makeUnion();
            
            // 어떤 인구이동도 일어나지 않았다면 종료
            if (!movePeople()) break;
            cnt++;
        }
        System.out.println(cnt);
    }

    private static void makeUnion() {
        // 각 연합을 만듦
        int groupNum = 1;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (union[i][j] == 0) {
                    bfs(i, j, groupNum);
                    groupNum++;
                }
            }
        }
    }

    private static void bfs(int r, int c, int groupNum) {
        int[][] mv = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

        Queue<Cor> q = new ArrayDeque<>();
        q.add(new Cor(r, c));
        union[r][c] = groupNum;

        int sum = A[r][c];
        int cnt = 1;

        while (!q.isEmpty()) {
            Cor now = q.poll();

            for (int i = 0; i < 4; i++) {
                int nr = now.r + mv[i][0];
                int nc = now.c + mv[i][1];

                if (nr < 0 || nc < 0 || N <= nr || N <= nc || union[nr][nc] != 0) continue;

                // L <= 인구 수 차이 <= R 라면 같은 그룹으로 묶음
                int diff = Math.abs(A[now.r][now.c] - A[nr][nc]);
                if (L <= diff && diff <= R) {
                    q.add(new Cor(nr, nc));
                    union[nr][nc] = groupNum;
                    sum += A[nr][nc];
                    cnt++;
                }
            }
        }

        // 현재 연합의 조정된 인구 수를 map에 저장
        map.put(groupNum, sum / cnt);
    }

    static class Cor {
        int r;
        int c;

        public Cor(int r, int c) {
            this.r = r;
            this.c = c;
        }
    }
    
    private static boolean movePeople() {
        boolean isMoved = false;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                
                // 현재 연합에 저장된 인구 수로 변경
                int people = map.get(union[i][j]);
                
                // 인구 이동이 일어나는지 확인
                if (A[i][j] != people) isMoved = true;
                A[i][j] = people;
            }
        }
        return isMoved;
    }

}

'Study > Algorithm' 카테고리의 다른 글

BOJ (Java) 13913번: 숨바꼭질 4  (1) 2025.06.26
BOJ (Java) 1806번: 부분합  (0) 2025.06.24
BOJ (Java) 1946번: 신입 사원  (1) 2025.06.14
BOJ (Java) 2638번: 치즈  (0) 2025.06.10
BOJ (Java) 16940번: BFS 스페셜 저지  (0) 2025.06.04