ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 16234 인구이동
    ALGORITHM/BOJ 2020. 12. 16. 12:33

    www.acmicpc.net/problem/16234

     

    16234번: 인구 이동

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

    www.acmicpc.net

    2020-12-16


    # 2019-08-24 풀이

    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.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.StringTokenizer;
     
    public class Main {
        public static int N, L, R, arr[][], map[][];
        public static boolean vtd[][];
        public static Queue<int[]> q, m;
        public static int dx[] = {-1010};
        public static int dy[] = {0-101};
        
        public static boolean solve(int input) {
            boolean check = false;
            while(!q.isEmpty()) {
                int tmp[] = q.poll();
                int x = tmp[0];
                int y = tmp[1];
                for(int i = 0; i < 4; i++) {
                    int nx = x + dx[i];
                    int ny = y + dy[i];
                    
                    if(nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
                    if(Math.abs(arr[nx][ny] - arr[x][y]) >= L && 
                            Math.abs(arr[nx][ny] - arr[x][y]) <= R
                            && !vtd[nx][ny]) {
                        check = true;
                        q.add(new int[] {nx, ny});
                        map[nx][ny] = input;
                        vtd[nx][ny] = true;
                    }
                }
            }
            
            return check;
        }
        
        public static void move(int color) {
            int count = 1;
            int pop = 0;
            while(!m.isEmpty()) {
                int tmp[] = m.poll();
                int x = tmp[0];
                int y = tmp[1];
                pop += arr[x][y];
                for(int i = 0; i < 4; i++) {
                    int nx = x + dx[i];
                    int ny = y + dy[i];
                    
                    if(nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
                    if(!vtd[nx][ny] && map[nx][ny] == map[x][y]) {
                        vtd[nx][ny] = true;
                        m.add(new int[] {nx, ny});
                        count++;
                    }
                }
            }
            int res = pop / count;
            for(int i = 0; i < N; i++
                for(int j = 0; j < N; j++)
                    if(map[i][j] == color) arr[i][j] = res;
        }
        
        public static void main(String[] args) throws Exception {
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(bf.readLine());
            N = Integer.parseInt(st.nextToken());
            L = Integer.parseInt(st.nextToken());
            R = Integer.parseInt(st.nextToken());
            arr = new int[N][N];
            for(int i = 0; i < N; i++) {
                st = new StringTokenizer(bf.readLine());
                for(int j = 0; j < N; j++)
                    arr[i][j] = Integer.parseInt(st.nextToken());
            }
            int count = 0;
            while(true) {
                int idx = 1;
                q = new LinkedList<int[]>();
                boolean check = false;
                vtd = new boolean[N][N];
                map = new int[N][N];
                for(int i = 0; i < N; i++) {
                    for(int j = 0; j < N; j++) {
                        if(!vtd[i][j]) {
                            q.add(new int[]{i, j});
                            vtd[i][j] = true;
                            map[i][j] = idx;
                            if(solve(idx)) {
                                check = true;
                            }
                            idx++;
                        }
                    }
                }
                if(!check) break;
                else count++;
                m = new LinkedList<int[]>();
                vtd = new boolean[N][N];
                for(int i = 0; i < N; i++) {
                    for(int j = 0; j < N; j++) {
                        if(!vtd[i][j]) {
                            vtd[i][j] = true;
                            m.add(new int[] { i, j });
                            move(map[i][j]);
                        }
                    }
                }
            }
            System.out.println(count);
        }
    }
     
    cs

     

    # 2020-12-16 풀이

    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
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
     
    public class Main {
        public static int N, L, R, people, count, answer, arr[][];
        public static boolean flag, vtd[][];
        public static Queue<int[]> q, f;
        public static int dx[] = {-1010};
        public static int dy[] = {0-101};
        
        public static void solve() {
            while(!q.isEmpty()) {
                int tmp[] = q.poll();
                int x = tmp[0];
                int y = tmp[1];
                
                for(int i = 0; i < 4; i++) {
                    int nx = x + dx[i];
                    int ny = y + dy[i];
                    
                    if(nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
                    else if(!vtd[nx][ny] && (Math.abs(arr[nx][ny] - arr[x][y]) >= L) && 
                            Math.abs(arr[nx][ny] - arr[x][y]) <= R) {
                        q.add(new int[] {nx, ny});
                        f.add(new int[] {nx, ny});
                        people += arr[nx][ny];
                        vtd[nx][ny] = true;
                        count++;
                        flag = true;
                    }
                }
            }
            if(flag) {
                open();
            }
        }
        
        public static void open() {
            int num = people/count;
            while(!f.isEmpty()) {
                int tmp[] = f.poll();
                int x = tmp[0];
                int y = tmp[1];
                arr[x][y] = num;
            }
        }
        
        public static void init() {
            for(int i = 0; i < N; i++)
                for(int j = 0; j < N; j++
                    vtd[i][j] = false;
        }
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            N = sc.nextInt();
            L = sc.nextInt();
            R = sc.nextInt();
            
            arr = new int[N][N];
            vtd = new boolean[N][N];
            q = new LinkedList<int[]>();
            f = new LinkedList<int[]>();
            answer = 0;
            
            for(int i = 0; i < N; i++
                for(int j = 0; j < N; j++
                    arr[i][j] = sc.nextInt();
            
            loop:while(true) {
                flag = false;
                for(int i = 0; i < N; i++) {
                    for(int j = 0; j < N; j++) {
                        if(!vtd[i][j]) {
                            people = 0;
                            count = 1;
                            vtd[i][j] = true;
                            q.add(new int[] {i, j});
                            f.add(new int[] {i, j});
                            people += arr[i][j];
                            solve();
                            f.clear();
                        }
                    }
                }
                if(flag) answer++;
                else break loop;
                init();
            }
            System.out.println(answer);
        }
    }
    cs

     

     

    #문제풀이

    1. N x N 땅을 돌면서 국경선을 열고 연합을 맺을 수 있는 나라들을 체크했다. 이 때 연합을 맺을 수 있는 나라를 f라는 또다른 queue에 따로 넣어줬었다. 

     

    2. 글로벌로 연합 맺을 국가의 갯수와 인구수를 따로 저장을 했고, 연합을 맺은 국가가 있는 경우 땅의 인구수를 업데이트 해주었다.

     

     

    # 비교

    작년 8월에도 풀었었던 문제이다. 오늘 푼 방식이 완벽하게 효율적이라고는 말하지 못하겠지만, 적어도 작년에 왜 저렇게 풀었던 방식이 비효율적이라는 것은 알았다. 굳이 필요하지 않은 부분을 넣어서 시간이 몇 배는 많이 들게 하는 코드였다. 다시 풀어보길 잘했다라는 생각이 든다.

    'ALGORITHM > BOJ' 카테고리의 다른 글

    [백준] 1761 정점들의 거리  (0) 2020.12.20
    [백준] 1175 배달  (2) 2020.12.20
    [백준] 11437, 11438 LCA (2)  (0) 2020.12.07
    [백준] 1946 신입사원  (0) 2020.12.06
    [백준] 9372 상근이의 여행  (0) 2020.12.05

    댓글

Programming Diary