본문 바로가기

알고리즘 스터디

[백준]16234 인구이동(C++)

728x90
반응형

백준 16234 인구이동

1. 문제

문제링크

2. 접근법

  • 문제 접근
    • 국경선을 상 하 좌 우로 열수 있고 각 나라와 L, R을 기준으로 연합하기 때문에 DFS로 완전탐색하면서 각 나라와 연합한다.
    • 각 나라와 연합여부를 체크할 배열, 연합 후의 인구수 유지를 위해 연합한 나라의 좌표(행, 열)을 담을 벡터, n*n크기의 땅에 해당하는 배열이 필요하다.
    • 연합을 위해 while문을 돌리고 while문 내에 flag를 생성한다. 각 나라에 방문하지 않은 경우, 위에 선언한 배열과 벡터값을 초기화 시키고 DFS를 돌린다. 
    • 연합하기 위해서는 나라의 수가 2이상이어야 하므로 2이상이면 연합한 국가와 인구수를 더하고 연합한 나라의 개수로 나눠 평균을 구한다. 또한 이때 flag를 true로 바꾼다.
    • 연합 후 인구수 유지를 위해 선언한 벡터에 연합한 나라의 위치를 넣어준 뒤 벡터의 사이즈만큼 for문을 돌리면서 n*n배열에 위에서 구한 평균값을 넣어준다.
    • flag가 true인 경우 answer를 증가시킨다.

3. 코드

#include<iostream>
#include<algorithm>
#include<vector>
#include<math.h>
#include<cstring>
#include<fstream>
using namespace std;
int N, L, R, cnt = 0, sum = 0;
int map[51][51];	//n*n크기의 땅
vector<pair<int, int>> vec;	//연합 후 인구수 유지를 위해 연합한 나라의 위치를 담을 벡터(행, 열)
bool checked[51][51]; //각 나라의 연합여부 체크할 배열 
//상 하 좌 우
int dr[4] = { 1, -1, 0, 0 };
int dc[4] = { 0, 0, -1, 1 };

void DFS(int row, int col)
{
	//4방향으로 탐색하면서 DFS를 돌림
	for (int i = 0; i < 4; i++)
	{
		int sr = row + dr[i];
		int sc = col + dc[i];

		//해당 위치에 방문하지 않았고 두나라의 인구차이가 L이상 R미만이면
		//sum 에 두나라의 인구수를 더해준 뒤 연합한 나라+1 시킨다.
		//후에 연합한 나라의 인구수를 업데이트 시켜주기 위해 
        	//vec에 해당나라의 위치(행, 열)를 넣는다.
		if (!checked[sr][sc])
		{
			if (0 <= sr && sr < N && 0 <= sc && sc < N)
			{
				int val = abs(map[row][col] - map[sr][sc]);
				if (L <= val && val <= R)
				{
					checked[sr][sc] = true;
					sum += map[sr][sc];
					cnt++;
					vec.push_back(make_pair(sr, sc));
					DFS(sr, sc);
				}
			}
		}
	}
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int ans = 0, avg = 0;
	cin >> N >> L >> R;

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

	while (1)
	{
		//flag, 체크배열 초기화
		bool flag = false;
		memset(checked, false, sizeof(checked));
		for (int i = 0; i < N; ++i)
		{
			for (int j = 0; j < N; ++j)
			{
				//방문하지 않았다면
				if (!checked[i][j])
				{
					//vec, cnt, sum, 체크배열 초기화
					vec.clear();
					cnt = 1;
					sum = map[i][j];
					checked[i][j] = true;
					//인구이동을 위해 처음 입력받은 나라의 위치를 넣고 DFS를 돌림
					vec.push_back(make_pair(i, j));
					DFS(i, j);
					//연합한 나라가 2이상이면 avg값을 구하고 
					//연합한 나라의 인구수를 avg로 업데이트시킴
					if (cnt >= 2)
					{
						flag = true;
						avg = sum / cnt;
						for (int k = 0; k < vec.size(); k++)
						{
							map[vec[k].first][vec[k].second] 
                            							= avg;
						}
					}
				}
			}
		}
		if (!flag)
			break;
		else
			ans++;
	}
	cout << ans << "\n";
	return 0;
}

4. 시간복잡도

DFS 알고리즘에서 인접행렬 이용한 방법이므로 기본적으로 O(V^2)의 시간복잡도를 가진다.

5. 결과

 

728x90
반응형

'알고리즘 스터디' 카테고리의 다른 글

[백준]14719_빗물(C++)  (0) 2021.08.10
[백준]17182_우주탐사선(C++)  (0) 2021.08.10
[프로그래머스]다단계 칫솔 판매(C++)  (0) 2021.08.03
[백준]10159 저울(C++)  (0) 2021.08.02
[백준]18513 샘터(C++)  (0) 2021.08.02