CS/Algorithm

[BOJ][16234] 인구이동

별토끼. 2019. 9. 1. 12:31
반응형
문제

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

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다. 오늘부터 인구 이동이 시작되는 날이다. 인구 이동은 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다. 국경선을 공유하는 두 나라의 인구 차이가 L명

www.acmicpc.net

풀이

연합국을 찾고, 연합국의 위치에 평균을 넣어주는 것을 반복하면서 더이상 연합국이 없을 때까지 이 과정을 반복하는 문제입니다.

1. 모든 위치를 탐색하여 국경선을 공유할 나라를 모읍니다. 

1-1. 한칸 한칸 탐색하는데, 두 나라의 인구 차이가 L과 R사이에 존재할 경우 team 벡터에 담고 인구 수를 카운팅해줍니다.

1-2. 연합국을 다 모았으면 인구 수/team.size()를 이용해 평균을 구합니다.

1-3. 다음 연합국을 모으기 위해 team벡터와 인구총합을 초기화 해줍니다.

2. isFin 이라는 변수를 두고, 연합국이 있을 경우 while문을 진행하도록 하고 없을 경우 while문을 빠져나오도록 합니다.

3. 이때, isFin이 true이면 결과값+1을 해주어 답을 구합니다.

코드
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#include <math.h>
using namespace std;
int n, l, r, res = 0;
bool isFin;
int map[51][51];
int visited[51][51];
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };	
int peo_num = 0;
vector<pair<int, int>> team;
void BFS(int a, int b) {
	queue<pair<int, int>> q;
	q.push(make_pair(a, b));
	visited[a][b] = 1;
	bool isOK = false;
	while (!q.empty()) {
		int x = q.front().first;
		int y = q.front().second;
		q.pop();
		team.push_back(make_pair(x, y));
		peo_num += map[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 (visited[nx][ny]==0 && (abs(map[x][y] - map[nx][ny]) >= l && abs(map[x][y] - map[nx][ny]) <= r)) {
				q.push(make_pair(nx, ny));
				visited[nx][ny] = 1;
				isOK = true;
				isFin = true;
			}
		}
	}
	//연합이 존재하지 않을 경우
	if (!isOK) {
		peo_num -= map[a][b];
		team.pop_back();
		return;
	}
	//연합 존재할 경우
	int avg = floor(peo_num / team.size());
	for (int i = 0; i < team.size(); i++) {
		map[team[i].first][team[i].second] = avg;
	}
	team.clear();
	peo_num = 0;
}
int main() {
	//입력
	cin >> n >> l >> r;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> map[i][j];
		}
	}
	
	//종료조건
	isFin = true;
	while (isFin) {
		isFin = false;
		memset(visited, 0, sizeof(visited));
		team.clear();
		peo_num = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (visited[i][j] == 0) {
					BFS(i, j);
				}
			}
		}
		//인구이동이 있었을 경우
		if (isFin) {
			res++;
		}
		
	}
	cout << res;
}
반응형