ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 16234 인구 이동
    Algorithm/구현(Brute force, Back tracking, etc.) 2021. 11. 18. 15:45
    728x90

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

     

    16234번: 인구 이동

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

    www.acmicpc.net


    - 그래프 탐색을 활용하는 구현 문제이다.

    - 시간 복잡도는 알 수가 없다.. 언제까지 인구 이동이 일어날 지를 모르기 때문

    - 가장 먼저, 모든 영역에 대해 BFS를 진행한다. 단 이미 다른 연합에 속한 영역은 진행하지 않는다. BFS를 진행할 때 마다 연합의 번호를 초깃값 1부터 1씩 늘려주면서 연합의 번호를 표시를 한다. 이는 나중에 인구 이동을 하기 위함이다.

    - 그 후, 모든 영역들이 어떤 연합에 속했는지를 구하면, 인구 이동을 진행한다. 이전에 BFS를 하는 과정에서 구했던 각 연합의 수 및 각 연합의 총 인구 수를 활용하여 최신화를 해 주면 된다.

    - 필자는 로직을 일찍 구현을 했는데, 디버깅하는데만 거의 1시간을 써버렸다. 그러다가 찾은 이유는 연합의 가능한 최대 경우의 수가 2500(50x50) 이었던 것.. 자꾸 segmentation fault가 떠서 미치는 줄 알았다. ㅠㅠ

    #include <iostream>
    #include <vector>
    #include <queue>
    #include <cstring>
    
    using namespace std;
    int arr[50][50];
    int visited[50][50];
    int sum_of_union_person[2501];
    vector<pair<int, int>> union_group[2501];
    int dx[] = { 0,0,1,-1 };
    int dy[] = { -1,1,0,0 };
    int n, l, r, union_num;
    
    void BFS(int start_x, int start_y) {
    	union_num++;
    	queue<pair<int, int>> q;
    	visited[start_x][start_y] = union_num;
    	q.push({ start_x,start_y });
    	union_group[union_num].push_back({ start_x,start_y });
    	sum_of_union_person[union_num] += arr[start_x][start_y];
    	while (!q.empty()) {
    		int x = q.front().first;
    		int y = q.front().second;
    		q.pop();
    		for (int i = 0; i < 4; i++) {
    			int nx = x + dx[i];
    			int ny = y + dy[i];
    			if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
    			if (visited[nx][ny] || abs(arr[x][y] - arr[nx][ny]) < l || abs(arr[x][y] - arr[nx][ny]) > r) continue;
    			visited[nx][ny] = union_num;
    			q.push({ nx,ny });
    			union_group[union_num].push_back({ nx,ny });
    			sum_of_union_person[union_num] += arr[nx][ny];
    			
    		}
    	}
    }
    int main() {
    	int answer = 0;
    	cin >> n >> l >> r;
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < n; j++) {
    			cin >> arr[i][j];
    		}
    	}
    	while (1) {
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n; j++) {
    				if (visited[i][j]) continue;
    				BFS(i, j);
    			}
    		}
    		if (union_num == n * n) break;
    		// 인구 이동
    		for (int i = 1; i <= union_num; i++) {
    			int n = union_group[i].size();
    			int value = sum_of_union_person[i] / n;
    			for (int j = 0; j < union_group[i].size(); j++) {
    				int x = union_group[i][j].first;
    				int y = union_group[i][j].second;
    				arr[x][y] = value;
    			}
    			while (!union_group[i].empty()) union_group[i].pop_back();
    		}
    		answer++;
    		union_num = 0;
    		memset(sum_of_union_person, 0, sizeof(sum_of_union_person));
    		memset(visited, 0, sizeof(visited));
    		
    	}
    	cout << answer;
    	return 0;
    }

    'Algorithm > 구현(Brute force, Back tracking, etc.)' 카테고리의 다른 글

    백준 16236 아기 상어  (0) 2021.11.19
    백준 16235 나무 재테크  (0) 2021.11.18
    백준 15686 치킨 배달  (0) 2021.11.18
    백준 15685 드래곤커브  (0) 2021.11.17
    백준 15694 사다리 조작  (0) 2021.11.17

    댓글

Designed by Tistory.