알고리즘 풀이/백준(Boj)

백준(BOJ) 16234번 인구 이동

100win10 2019. 11. 22. 16:03

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

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다. 오늘부터 인구 이동이 시작되는 날이다. 인구 이동은 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다. 국경선을 공유하는 두 나라의 인구 차이가 L명

www.acmicpc.net

풀이 :

 

연합이 될 수있는 칸들을 BFS를 통해서 탐색한다. 연합이 자기 자신을 제외하고 하나라도 있다면

 

ans를 +1 해주고 계속해서 연합을 탐색하고 아니라면 바로 종료한다.

 

연합들을 만들었다면 값들을 모두 바꾸어 주어야 하는데 스택을 이용하여 BFS를 통해 방문한 좌표들을

 

담은 후 새로 구한 값으로 다 바꾸어주자.

 

코드( C ++ )

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstring>
using namespace std;
int n, l, r;
int a[50][50];
int visited[50][50];
const int dy[4] = { 1,-1,0,0 };
const int dx[4] = { 0,0,1,-1 };
bool bfs(int l, int r)
{
memset(visited, 0, sizeof(visited));
bool isTrue = false;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
{
if (visited[i][j]) continue;
queue<pair<int, int>> q;
q.push({ i,j });
visited[i][j] = true;
//기록을 위한 스택
stack<pair<int, int>> st;
st.push({ i,j });
int sum = a[i][j];
while (!q.empty())
{
int y = q.front().first;
int x = q.front().second;
q.pop();
for (int k = 0; k < 4; ++k)
{
int ny = y + dy[k];
int nx = x + dx[k];
if (!(0 <= ny && ny < n && 0 <= nx && nx < n)) continue;
if (visited[ny][nx]) continue;
int diff = abs(a[ny][nx] - a[y][x]);
if (l <= diff && diff <= r)
{
q.push({ ny,nx });
st.push({ ny,nx });
visited[ny][nx] = true;
// 연합이 생겼다면 true
isTrue = true;
sum += a[ny][nx];
}
}
}
int ret = sum / st.size();
while (!st.empty())
{
int y = st.top().first;
int x = st.top().second;
st.pop();
a[y][x] = ret;
}
}
return isTrue;
}
int main()
{
cin >> n >> l >> r;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cin >> a[i][j];
int ans = 0;
while (1)
{
if (bfs(l, r))
ans++;
else
break;
}
cout << ans << "\n";
return 0;
}
view raw .cpp hosted with ❤ by GitHub