알고리즘 :: 큰돌 :: Chapter 3 - 완전탐색/백트래킹 :: 백준 16234 인구 이동

Embedded June·2023년 7월 6일
0
post-thumbnail

문제

문제 링크

해설

  • 인구 이동을 하려면 어떤 정보들이 필요할까요?
    • 국경을 개방한 국가의 좌표가 필요합니다.
    • 그래야 좌표들을 토대로 인구의 합과 평균을 구할 수 있기 때문입니다.
  • 따라서, 임의의 좌표 (y, x)에서 DFS를 수행할 때, 국경을 개방할 조건 (L <= 인구 차이 <= R)을 만족한다면 재귀를 수행함과 동시에 외부 저장소에 좌표를 따로 저장합니다.
  • 이렇게 DFS를 1회 수행하면, 임의의 좌표 (y, x)를 기준으로 국경을 개방할 수 있는 ‘연합’이 만들어집니다. 저희는 ‘연합’의 좌표를 모두 저장해놨기 때문에 순회하며 인구수 합을 구하고 평균으로 값을 갱신할 수 있습니다.
  • 프로그램의 종료조건은 무엇일까요? 더 이상 인구 이동이 일어나지 않을 때 일 것입니다.
  • 모든 점에 대해 DFS를 수행했을 때 연합이 단 하나도 만들어지지 않았다면? 루프문을 빠져나옵니다.

코드

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

constexpr int d[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

int N, L, R;
int land[50][50];
bool visited[50][50];
vector<pair<int, int>> pos;

int DFS(int y, int x) {
	visited[y][x] = true;
	pos.emplace_back(y, x);
	int ret = land[y][x];
	for (auto i : d) {
		int ny = y + i[0], nx = x + i[1];
		if (ny < 0 || nx < 0 || ny >= N || nx >= N || visited[ny][nx]) continue;
		int diff = abs(land[y][x] - land[ny][nx]);
		if (L <= diff && diff <= R) ret += DFS(ny, nx);
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	cin >> N >> L >> R;
	for (int y = 0; y < N; y++)
		for (int x = 0; x < N; x++)
			cin >> land[y][x];

	int answer = 0;
	while (true) {
		int sum;
		bool is_moved = false;
		for (int y = 0; y < N; y++) {
			for (int x = 0; x < N; x++) {
				if (visited[y][x]) continue;
				pos.clear();
				sum = DFS(y, x);
				if (pos.size() == 1) continue;
				for (const auto& i : pos)
					land[i.first][i.second] = sum / pos.size();
				is_moved = true;
			}
		}
		if (!is_moved) break;
		answer++;
		memset(visited, false, sizeof(visited));
	}
	cout << answer << '\n';
	return 0;
}

소스코드 링크

결과

profile
임베디드 시스템 공학자를 지망하는 컴퓨터공학+전자공학 복수전공 학부생입니다. 타인의 피드백을 수용하고 숙고하고 대응하며 자극과 반응 사이의 간격을 늘리며 스스로 반응을 컨트롤 할 수 있는 주도적인 사람이 되는 것이 저의 20대의 목표입니다.

0개의 댓글