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


[알고리즘풀이]

Union - Find 를 이용해서 문제를 해결했습니다.

( 대부분 DFS, BFS로 문제를 푸셨더라고요....!! DFS, BFS 풀이는 다른 분들 블로그 참고하시면 될 것 같습니다. )

 

n : 도시의 크기를 나타내는 수 ( n * n : 도시의 크기 )

N[x][y] : 현재 도시별 인구가 담겨있는 배열.

 

1) 번호 부여.

(i , j) 도시의 번호 = i * n + j 로 정의하면, 모든 도시에게 0 ~ (n * n - 1)까지 번호를 하나씩 부여할 수 있습니다.

 

2) Union - find

(0, 0)부터 (n-1, n-1)까지 모든 도시에게 번호를 부여한 후, 1차원 배열로 Union - find 를 진행합니다.

N[i][j] 와 N[k][l] 이 인접해있고, 두 도시의 인구 차이가 L 보다 크거나 같고, R 보다 작거나 같으면 (i , j) 와 (k, l)을 Union(Merge) 해줍니다.

		for (int i = 0; i < n; i++)
			for (int j = 0; j < n - 1; j++)
				if (check(abs(N[i][j] - N[i][j + 1]))) {
					merge(i * n + j, i * n + (j + 1));
					stop++;
				}

		for (int j = 0; j < n; j++)
			for (int i = 0; i < n - 1; i++)
				if (check(abs(N[i][j] - N[i + 1][j]))) {
					merge(i * n + j, (i + 1) * n + j);
					stop++;
				}

3) 도시 인구 초기화.

조건에 해당되서 Union된 도시가 있다면, 인구 이동을 진행해야 합니다.

각 도시별로 root 값을 다 find 한 후, 같은 root 값을 가지는 도시들은 하나의 vector에 Push합니다.

		vector<int> g[2500];
		for (int i = 0; i < n * n; i++){
			g[find(i)].push_back(i);
		}

이제 root 값이 같은 도시들은 모두 하나의 vector에 들어가 있습니다.

따라서,  size가 0 보다 큰 모든 vector 들(root 값이 같은 도시가 있는 도시들)을 하나씩 순회하며 인구를 초기화해주면 됩니다.

		for (int i = 0; i < n * n; i++) {
			int cnt = g[i].size();
			if (cnt > 0) {
				int sum = 0;
				for (int j = 0; j < g[i].size(); j++) {
					sum += N[g[i][j] / n][g[i][j] % n];
				}
				int avg = sum / cnt;
				for (int j = 0; j < g[i].size(); j++) {
					N[g[i][j] / n][g[i][j] % n] = avg;
				}
			}
		}

 

4) 최종 코드

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>

using namespace std;

int n, l, r, N[50][50];
int p[2500] = {};
int h[2500] = {};
int f[2500] = {};

bool check(int a) {
	if (l <= a && a <= r)
		return true;
	return false;
}

int find(int x) {
	if (p[x] == x)
		return x;
	else {
		return p[x] = find(p[x]);
	}
}

void merge(int x, int y) {
	x = find(x);
	y = find(y);

	if (x == y)
		return;

	if (h[x] < h[y])
		p[x] = y;
	else {
		p[y] = x;
		if (h[x] == h[y])
			h[x]++;
	}
	return;
}

int main(void) {
	cin >> n >> l >> r;

	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> N[i][j];

	int c = 0;

	while (1) {
		for (int i = 0; i < n * n; i++) {
			p[i] = i;
			h[i] = 0;
		}

		int stop = 0;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n - 1; j++)
				if (check(abs(N[i][j] - N[i][j + 1]))) {
					merge(i * n + j, i * n + (j + 1));
					stop++;
				}

		for (int j = 0; j < n; j++)
			for (int i = 0; i < n - 1; i++)
				if (check(abs(N[i][j] - N[i + 1][j]))) {
					merge(i * n + j, (i + 1) * n + j);
					stop++;
				}
		if (stop == 0)
			break;

		vector<int> g[2500];
		for (int i = 0; i < n * n; i++){
			g[find(i)].push_back(i);
		}

		for (int i = 0; i < n * n; i++) {
			int cnt = g[i].size();
			if (cnt > 0) {
				int sum = 0;
				for (int j = 0; j < g[i].size(); j++) {
					sum += N[g[i][j] / n][g[i][j] % n];
				}
				int avg = sum / cnt;
				for (int j = 0; j < g[i].size(); j++) {
					N[g[i][j] / n][g[i][j] % n] = avg;
				}
			}
		}
		c++;
	}
	cout << c;
}

 

+ Recent posts