Problem Solving
알고리즘 :: 백준 :: 16234 - 인구 이동
soreDemo
2025. 1. 16. 00:59
❔문제
🔄 문제 및 입출력 조건 파악
- 땅 크기 N×N (1 ≤ N ≤ 50)
- L ≤ 인구 차이 ≤ R (1 ≤ L ≤ R ≤ 100)
✏️ 문제풀이
문제에 인구 이동 로직이 나와있기 때문에 그대로 실수없이 구현하면 되는 문제입니다.
인구 이동 과정은 ① 연합 만들기 - ② 인구 이동 - ③ 인구 이동 ? 시간 증가 : 종료 후 정답 출력으로 요약할 수 있습니다. 코드로 간략하게 나타내면 다음과 같습니다.
while (true) {
// 1. 연합 만들기
for (int y = 0; y < N; ++y) {
for (int x = 0; x < N; ++x) {
if (visited[y][x]) continue;
sum = 0;
dfs(y, x);
// 2-1. 연합이 안 만들어졌다? 다른 칸 검사
if (unite.size() == 1) {
unite.pop_back();
continue;
}
// 2-2. 연합이 만들어졌다면, 인구 이동
startMove();
moveFlag = true;
}
}
// 3. 인구 이동 여부에 따라 시간증가 or 프로그램 종료
if (!moveFlag) break;
ans++;
}
연합은 임의의 시작점을 기점으로 DFS를 1회 돌리면 만들 수 있습니다.
갈 수 있는 모든 국가에 방문표시 및 외부 배열에 좌표를 저장합니다.
이렇게 연합이 만들어지면, 인구 이동을 실시합니다.
모든 점을 검사했는데, 인구 이동이 발생하지 않았다면 정답을 출력합니다.
📝 코드
#include <bits/stdc++.h>
using namespace std;
constexpr int dy[] = {1, 0, -1, 0};
constexpr int dx[] = {0, 1, 0, -1};
int N, L, R, sum;
bool visited[101][101];
array<array<int, 101>, 101> arr;
vector<pair<int, int>> unite;
void dfs(int y, int x) {
visited[y][x] = true;
unite.push_back({y, x});
sum += arr[y][x];
for (int i = 0; i < 4; ++i) {
int ny = y + dy[i], nx = x + dx[i];
if (ny < 0 || nx < 0 || ny >= N || nx >= N || visited[ny][nx]) continue;
int diff = abs(arr[ny][nx] - arr[y][x]);
if (L <= diff && diff <= R) dfs(ny, nx);
}
}
void startMove() {
int newVar = sum / unite.size();
while (!unite.empty()) {
int y, x; tie(y, x) = unite.back();
arr[y][x] = newVar;
unite.pop_back();
}
}
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 >> arr[y][x];
unite.reserve(N * N);
int ans = 0;
while (true) {
bool moveFlag = false;
memset(visited, false, sizeof(visited));
for (int y = 0; y < N; ++y) {
for (int x = 0; x < N; ++x) {
if (visited[y][x]) continue;
sum = 0;
dfs(y, x);
if (unite.size() == 1) {
unite.pop_back();
continue;
}
startMove();
moveFlag = true;
}
}
if (!moveFlag) break;
ans++;
}
cout << ans;
}
🕧 결과