알고리즘/PS - 백준

[백준 16234 - C++] 인구 이동

excited-hyun 2021. 9. 24. 15:03
반응형

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

 

16234번: 인구 이동

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

www.acmicpc.net

 

문제

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

오늘부터 인구 이동이 시작되는 날이다.

인구 이동은 하루 동안 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다.

  • 국경선을 공유하는 두 나라의 인구 차이가 L명 이상, R명 이하라면, 두 나라가 공유하는 국경선을 오늘 하루 동안 연다.
  • 위의 조건에 의해 열어야하는 국경선이 모두 열렸다면, 인구 이동을 시작한다.
  • 국경선이 열려있어 인접한 칸만을 이용해 이동할 수 있으면, 그 나라를 오늘 하루 동안은 연합이라고 한다.
  • 연합을 이루고 있는 각 칸의 인구수는 (연합의 인구수) / (연합을 이루고 있는 칸의 개수)가 된다. 편의상 소수점은 버린다.
  • 연합을 해체하고, 모든 국경선을 닫는다.

각 나라의 인구수가 주어졌을 때, 인구 이동이 며칠 동안 발생하는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N, L, R이 주어진다. (1 ≤ N ≤ 50, 1 ≤ L ≤ R ≤ 100)

둘째 줄부터 N개의 줄에 각 나라의 인구수가 주어진다. r행 c열에 주어지는 정수는 A[r][c]의 값이다. (0 ≤ A[r][c] ≤ 100)

인구 이동이 발생하는 일수가 2,000번 보다 작거나 같은 입력만 주어진다.

출력

인구 이동이 며칠 동안 발생하는지 첫째 줄에 출력한다.

 

풀이

저는 두개의 큐를 사용해서 문제를 풀었습니다.

  • BFS 실행을 위한 큐
  • 이어진 나라들을 저장해 두는데에 사용하는 큐

 

  1. BFS 알고리즘을 사용해서 국경을 열수 있는 나라들을 모두 확인합니다.
  2. 연결된 나라들의 총 수와 인구수를 모두 계산합니다. 또한 그 나라들끼리 하나의 큐에 들어가도록 해줍니다.
  3. 큐에서 하나씩 꺼내면서 연결된 나라들의 인구를 이동시켜줍니다.
  4. 모든 나라들을 각각 확인하면서 인구 이동이 몇 번 일어난지 확인합니다.
  5. 이때 인구이동이 더 이상 일어나지 않았다면 반복을 종료하게 됩니다.

 

#include <cstdio>
#include <queue>
#include <cstdlib>

using namespace std;

int n, l, r;
int map[50][50];
int country[50][50];
int visited[50][50];

int R[4] = {1, -1, 0, 0};
int C[4] = {0, 0, 1, -1};

int main () {
    scanf("%d %d %d", &n, &l, &r);
    int ans = 0;
    int idx = 1;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            country[i][j] = idx;
            idx++;
            scanf("%d", &map[i][j]);
        }
    }
    
    while(1){
        int move = 0;
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                
                if(visited[i][j] == 0){
                    queue<pair<pair<int, int>, int>> q;
                    queue<pair<pair<int, int>, int>> q2;
                    q.push(make_pair(make_pair(i, j), country[i][j]));      //BFS에 사용
                    q2.push(make_pair(make_pair(i, j), country[i][j]));     //인구 이동에 사용
                    
                    visited[i][j] = country[i][j];      //방문시 연결된 나라 번호 저장
                    int cnt = 1;                    //연결된 나라 수
                    int total = map[i][j];          //연결된 나라 총 인구수
                    
                    while(!q.empty()){
                        int nowR = q.front().first.first;
                        int nowC = q.front().first.second;
                        int num = q.front().second;
                        q.pop();
                        for(int i=0; i<4; i++){
                            int nextR = nowR + R[i];
                            int nextC = nowC + C[i];
                            if(nextR<0 || nextR>=n || nextC<0 || nextC>=n)
                                continue;
                            if(visited[nextR][nextC]!=0)
                                continue;
                            
                            //연결 가능
                            if( (abs(map[nowR][nowC] - map[nextR][nextC]) >= l) && (abs(map[nowR][nowC] - map[nextR][nextC]) <= r)){
                                cnt++;
                                total += map[nextR][nextC];
                                move++;
                                q.push(make_pair(make_pair(nextR, nextC), num));
                                q2.push(make_pair(make_pair(nextR, nextC), num));
                                visited[nextR][nextC] = num;
                            }
                        }
                    }
                    
                    //인구 이동 시킴
                    while(!q2.empty()){
                        int nowR = q2.front().first.first;
                        int nowC = q2.front().first.second;
                        q2.pop();
                        map[nowR][nowC] = total / cnt;
                    }
                }
            }
        }
        //인구 이동이 일어나지 않음 -> 종료
        if(move == 0)
            break;
        
        ans++;
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                visited[i][j] = 0;
            }
        }
        
    }
    printf("%d\n", ans);
    
}
728x90
반응형

'알고리즘 > PS - 백준' 카테고리의 다른 글

[백준 17144 - Java] 미세먼지 안녕!  (0) 2021.10.04
[백준 17142 - Java] 연구소 3  (0) 2021.09.30
[백준 15683 - C++] 감시  (0) 2021.09.23
[백준 3190 - C++] 뱀  (0) 2021.09.16
[백준 14891 - C++] 톱니바퀴  (0) 2021.09.16