백준 16234 인구이동 C++
2023. 8. 23. 17:07ㆍ알고리즘
문제
N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다.
오늘부터 인구 이동이 시작되는 날이다.
인구 이동은 하루 동안 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다.
- 국경선을 공유하는 두 나라의 인구 차이가 L명 이상, R명 이하라면, 두 나라가 공유하는 국경선을 오늘 하루 동안 연다.
- 위의 조건에 의해 열어야하는 국경선이 모두 열렸다면, 인구 이동을 시작한다.
- 국경선이 열려있어 인접한 칸만을 이용해 이동할 수 있으면, 그 나라를 오늘 하루 동안은 연합이라고 한다.
- 연합을 이루고 있는 각 칸의 인구수는 (연합의 인구수) / (연합을 이루고 있는 칸의 개수)가 된다. 편의상 소수점은 버린다.
- 연합을 해체하고, 모든 국경선을 닫는다.
각 나라의 인구수가 주어졌을 때, 인구 이동이 며칠 동안 발생하는지 구하는 프로그램을 작성하시오.
코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <stdbool.h>
#include <cstring>
using namespace std;
int n, l, r;
int arr[51][51];
int dif[51][51][4];
int visited[51][51];
int mark[51][51];
int total, cnt;
int st;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {-1, 0, 1, 0};
bool check(int x, int y) {
if (x < 0 || y < 0 || x >= n || y >= n) {
return false;
}
return true;
}
void allocate(int x, int y) {
arr[y][x] = total;
visited[y][x] = 1;
for (int i = 0;i < 4;i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (check(nx, ny) == false || visited[ny][nx]) {
continue;
}
if (mark[ny][nx] == st) {
allocate(nx, ny);
}
}
return;
}
void dfs(int x, int y) {
total += arr[y][x];
cnt++;
for (int i = 0;i < 4;i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (dif[y][x][i] == -1) { // 만약 갈 수 없으면 체크하지 않는다
continue;
}
if (mark[ny][nx] != 0) {
continue;
}
if (dif[y][x][i] >= l && dif[y][x][i] <= r) {
mark[ny][nx] = mark[y][x];
dfs(nx, ny);
}
}
return;
}
int main(void) {
cin.tie(NULL);
ios::sync_with_stdio(false);
cin >> n >> l >> r;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> arr[i][j];
}
}
int ans = 0;
while(1) {
memset(dif, 0, sizeof(dif));
memset(mark, 0, sizeof(mark));
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
for (int w = 0;w < 4;w++) {
int ny = i + dy[w];
int nx = j + dx[w];
// 위쪽
if (check(nx, ny) == false) {
dif[i][j][w] = -1; // 범위밖에 가서 체크할 필요가 없다
}
else { // 차이를 저장한다
dif[i][j][w] = abs(arr[i][j] - arr[ny][nx]);
}
}
}
}
st = 1;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (mark[i][j] != 0) {
continue;
}
else {
// 합쳐질 수 있는 부분을 구분한다
mark[i][j] = st;
dfs(j, i);
total = total / cnt;
allocate(j, i);
memset(visited, 0, sizeof(visited));
total = 0, cnt = 0;
st++;
}
}
}
if (st > n*n) {
break;
}
ans++;
}
cout << ans << endl;
return 0;
}
'알고리즘' 카테고리의 다른 글
백준 14500 테트로미노 c++ (dfs) (0) | 2023.09.01 |
---|---|
후... (0) | 2023.08.29 |
백준 이차원 배열과 연산 17140 C++ (1) | 2023.08.22 |
백준 16236 아기상어 C++ (5) | 2023.08.18 |
Softeer GBC C++ (0) | 2023.08.08 |