Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- sw expert academy
- 15662
- 서울에서경산까지
- 재귀
- 크로스핏
- DP
- 브루트포스
- 4811
- 1로만들기2
- 14863
- BOJ
- 회전하는큐
- Python
- 해시해킹
- 1781
- Flutter
- 그리디
- 재귀함수
- D1
- 15353
- C++
- Crossfit
- BOJ14889
- 삼성
- spring boot
- 동적프로그래밍
- 스택
- dart
- 26008
- 백준
Archives
- Today
- Total
곧죽어도 콛잉
[브루트 포스 / BOJ 16234 / C++] 인구 이동 본문
https://www.acmicpc.net/problem/16234
16234번: 인구 이동
N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모
www.acmicpc.net
1) while(1)을 통해 계속해서 인구 이동을 체크하는 로직을 생각한다. 만약 인구이동이 발생됐다면, day++가 되고 그게 아니라면 종료하고 즉시 day를 출력한다.
2)모든 칸에 대한 인구이동을 dfs로 확인한다.
3)발생한 인구이동에 대한 연합의 인구수와 연합들의 위치를 저장하여, 평균을 구해 인구수를 맞춘다. 이때, 연합이 단 한개라면, 그 즉시 while문을 종료한다.
뭔가 쉬운듯 복잡....
우선 dfs나 bfs로 로직을 짜는 건 어렵지 않았을 것이다. 상하좌우와 차이를 구해서 그 차이가 L과 R 이내면 그즉시 연합으로 표시하면 된다. 이런식으로 연합을 늘려나간다.
모든 연합이 가능한 경우를 확인했다면, 그 연합들의 평균을 구한다. 그리고 그 연합들을 평균값으로 갱신해준다.
그런데, 연합을 이루는 국가가 단 한개라면, 그건 인구이동이 발생하지 않는 다는 것을 의미하므로 프로그램을 종료한다!
이 문제의 핵심은 도대체 어디에서 인구이동이 발생하지 않았다고 표시하고, 종료해줄까를 생각하는 것이 중요한 것 같다..!! 안그러면 헤맨다. 간단하게 while - flag 형식을 써주자..!
#include <bits/stdc++.h>
using namespace std;
int N, L, R, res;
int bd[54][54], vis[54][54];
int dy[4] = {1, 0, -1, 0};
int dx[4] = {0, 1, 0, -1};
int unions;
vector<pair<int,int>> uni_p;
void dfs(int y, int x){
for(int i = 0 ; i < 4 ; i++){
int ny = y + dy[i];
int nx = x + dx[i];
if(ny >= N || nx >= N || ny < 0 || nx < 0) continue;
if(vis[ny][nx]) continue;
int diff = abs(bd[ny][nx] - bd[y][x]);
if(diff >= L && diff <= R){
unions += bd[ny][nx];
uni_p.push_back({ny,nx});
vis[ny][nx]=1;
dfs(ny, nx);
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N >> L >> R;
for(int i = 0 ; i < N ; i++){
for(int j = 0 ; j < N ; j++){
cin >> bd[i][j];
}
}
while (true) {
int flag = 0;
memset(vis, 0, sizeof(vis));
for(int i = 0 ; i < N ; i++){
for(int j = 0 ; j < N ; j++){
if(!vis[i][j]){ // 해당좌표가 union이고 아직 방문안했으면 union연합시키기.
if(uni_p.size()) uni_p.clear();
uni_p.push_back({i, j});
unions=bd[i][j];
vis[i][j] = 1;
dfs(i,j);
if(uni_p.size()==1) {continue;} // uni할게 없으면 인구 이동 없음.
int avg = unions / uni_p.size();
for(auto k : uni_p){
bd[k.first][k.second] = avg;
flag=1;
} // 연합 숫자 맞춰주기. 인구이동발생!
}
}
}
if(!flag) break; // 인구이동 발생 없을시 중단.
res++;
}
cout << res;
}
'Coding Test > C++' 카테고리의 다른 글
[그래프 / BOJ 17471 / C++] 게리맨더링 (0) | 2023.04.27 |
---|---|
[비트마스킹 / BOJ 1285 / C++] 동전 뒤집기 (0) | 2023.04.27 |
[비트마스킹 / BOJ 19942 / C++] 다이어트 (0) | 2023.03.29 |
[브루트 포스 / BOJ 14620 / C++] 꽃길 (0) | 2023.03.21 |
[브루트 포스 / BOJ 2529 / C++] 부등호 (0) | 2023.03.19 |
Comments