알고리즘 문제 풀이/BOJ

[backjoon]16234 인구 이동 java

v 2021. 9. 26. 16:00

16234번: 인구 이동

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모

www.acmicpc.net

좀더 간결하게 풀이해서 포스팅 (링크)
이전엔 방문체크를 다른 배열을 둬서 했는데 그런 것 없이 한번에 풀이하여서 좀더 깔끔한 풀이가 됨

풀이 개요

BFS나 DFS 와 같이 완전 탐색 이용해서 풀이하면 되는 문제.
나는 BFS를 사용하였고, BFS 두 번 돌리면 시간 초과가 일어나기에 한번 BFS를 돌릴 때, 인구 이동시 필요한 값들을 다 저장해야한다.
문제 풀이시 약간 헷갈려서 같은 역할을 하는 방문 체크를 위한 배열이 2개 있었는데 이 문제로 시간 초과도 떴다.
불필요한 부분은 제외하고 면밀한 풀이가 필수!

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import java.io.*;
import java.util.*;
 
class Main {
    static int N, L, R, marking;
    static boolean flag;
    static int[][] map , stamp;
    static boolean[][] marked;
    static ArrayList<Dot>[] arr;
    static int[] sum;
    static int max = 50 * 50 +1;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
 
        N = Integer.parseInt(st.nextToken());
        L = Integer.parseInt(st.nextToken()); // min
        R = Integer.parseInt(st.nextToken()); // max
 
        map = new int[N + 1][N + 1];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                int temp = Integer.parseInt(st.nextToken());
                map[i][j] = temp;
            }
        }
        int answer = 0;
 
        while (true) {
            marked = new boolean[N + 1][N + 1]; // 재탐색 안 하기 위함.
            flag = false;
            marking = 0;
            arr = new ArrayList[max];
            sum = new int[max];
            for(int i = 0; i < max; i++) {
                arr[i] = new ArrayList<>();
            }
            //국경 확인 -> 전체를 확인하면서 국경을 파악한다. -> stamp를 남겨서 그룹화함.
            stamp = new int[N][N];
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if(marked[i][j]) continue;
                    boundary(new Dot(i, j));
                    marked[i][j] = true;
                }
            }
 
            if(!flag) break;
            answer++;
            //인구 이동
            move();
        }
        System.out.println(answer);
    }
 
    public static void move() {
        for(int i = 0; i < max; i++) {
            ArrayList<Dot> list = arr[i];
            if(list.size() == 0continue;
            int totalSum = sum[i];
            int cal = totalSum/list.size();
            for(Dot d : list) {
                map[d.row][d.col] = cal;
            }
        }
 
    }
    public static void boundary(Dot d) {
        Queue<Dot> queue = new LinkedList<Dot>();
 
        int[][] dirs = { { 10 }, { -10 }, { 01 }, { 0-1 } };
        queue.add(d);
        marked[d.row][d.col] = true;
        stamp[d.row][d.col] = ++marking;
        arr[stamp[d.row][d.col]].add(d);
        sum[stamp[d.row][d.col]] += map[d.row][d.col];
        while (!queue.isEmpty()) {
            Dot cur = queue.poll();
 
            for (int dir = 0; dir < 4; dir++) {
                int nextR = cur.row + dirs[dir][0];
                int nextC = cur.col + dirs[dir][1];
 
                if (nextR < 0 || nextC < 0 || nextR >= N || nextC >= N)
                    continue;
                if (marked[nextR][nextC])
                    continue;
 
                int cal = Math.abs(map[cur.row][cur.col] - map[nextR][nextC]);
 
                if (cal < L || cal > R)
                    continue;
 
                marked[nextR][nextC] = true;
                marked[nextR][nextC] = true;
                queue.add(new Dot(nextR, nextC));
                arr[stamp[d.row][d.col]].add(new Dot(nextR, nextC));
                sum[stamp[d.row][d.col]] += map[nextR][nextC];
                flag = true;
            }
        }
    }
}
class Dot{
    int row;
    int col;
    Dot(int row, int col){
        this.row = row;
        this.col = col;
    }
}
cs
반응형