반응형
01-28 19:17
Today
Total
«   2025/01   »
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
관리 메뉴

개발하는 고라니

[백준] 16234번 : 인구 이동 본문

Programming/백준

[백준] 16234번 : 인구 이동

조용한고라니 2021. 2. 9. 02:57
반응형
 

16234번: 인구 이동

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

www.acmicpc.net

[BFS]

나는 보통 visit를 boolean으로 하여 true/false로 구분하지만, 이런 영역을 나눠야 하는 문제에서는 int visit[][]로 하는 편이 좋다. 점(i, j)에서 인접한 점과의 차(a)가 l <= a <= r인 곳을 Queue에 넣으며 동시에 같은 영역이라고 생각한다. 큐에 넣으면서 반드시 동일 영역의 인구 수를 sum에 더해주고, 동일 영역의 개수가 몇 개인지도 계속 체크해주어야 한다.

 

Queue가 비었으면 동일한 영역 모든 곳의 값을 sum / cnt로 변경한다.

 

각 루프에서 초기화와 visit에 주의하자.

# Code </>

public class Main {

    static class Point{
        int y, x;
        public Point(int yy, int xx){
            y = yy; x = xx;
        }
    }
    static int[][] map = new int[50][50], visit;
    static int[] Y = {-1, 1, 0, 0}, X = {0, 0, -1, 1};
    static int n, l, r, cnt = 0, sum = 0, area = 0;

    static boolean isUnion(int y, int x){
        boolean flag = false;

        for(int a=0; a<4; a++){
            int ny = y+Y[a];
            int nx = x+X[a];

            if(ny < 0 || nx < 0 || ny >= n || nx >= n || visit[ny][nx] != 0) continue;

            if(Math.abs(map[y][x] - map[ny][nx]) >= l && Math.abs(map[y][x] - map[ny][nx]) <= r) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    static boolean BFS(){
        boolean open = false;
        Queue<Point> Q = new LinkedList<>();

        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++) {
                cnt = 1;
                sum = map[i][j];

                if (visit[i][j] == 0 && isUnion(i, j)) {
                    open = true;
                    area++;
                    visit[i][j] = area;
                    Q.add(new Point(i, j));

                    while (!Q.isEmpty()) {
                        Point p = Q.poll();
                        int y = p.y;
                        int x = p.x;

                        for (int a = 0; a < 4; a++) {
                            int ny = y + Y[a];
                            int nx = x + X[a];

                            if (ny < 0 || nx < 0 || ny >= n || nx >= n || visit[ny][nx] != 0) continue;

                            if (Math.abs(map[y][x] - map[ny][nx]) >= l && Math.abs(map[y][x] - map[ny][nx]) <= r) {
                                cnt++;
                                sum += map[ny][nx];
                                visit[ny][nx] = area;
                                Q.add(new Point(ny, nx));
                            }
                        }
                    }
                    for (int a = 0; a < n; a++)
                        for (int b = 0; b < n; b++)
                            if (visit[a][b] == area)
                                map[a][b] = sum / cnt;
                }
            }

        return open;
    }

    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());

        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());
        }

        int time = 0;
        while(true){
            area = 0;
            visit = new int[50][50];
            if(!BFS()) break;
            time++;
        }

        System.out.println(time);
    }
}
반응형

'Programming > 백준' 카테고리의 다른 글

[백준] 2638번 : 치즈  (0) 2021.02.12
[백준] 1167번 : 트리의 지름  (0) 2021.02.10
[백준] 1325번 : 효율적인 해킹  (0) 2021.02.09
[백준] 3055번 : 탈출  (0) 2021.02.08
[백준] 1162번 : 도로 포장  (0) 2021.02.08
Comments