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 | 31 |
Tags
- GridItem
- zustand
- 컴퓨터네트워크
- react fsd
- 리렌더링최적화
- react-router-dom
- 반응형 css
- 페이지전환
- gitbub desktop
- git
- 세로모드끄기
- @published 프로퍼티 래퍼
- 동기 함수 내에서 비동기 함수 호출
- 리액트최적화
- 블로그업로드확인
- react상태관리라이브러리
- C++
- CSS
- 페이지이동함수
- 비동기함수
- 원격저장소 연결
- 가로모드끄기
- zustand란
- featured-sliced-design
- modal 관리
- BFS
- react hook
- @environmentobject 프로퍼티 래퍼
- react modal
- @observedobject 프로퍼티 래퍼
Archives
- Today
- Total
leebaek
[BOJ/16234번인구이동] c++ / BFS 본문
문제
각 나라의 인구 수가 주어졌을 때, 인구 이동이 며칠동안 발생하는지 구하는 문제
-인접한 나라의 인구 수 차이가 L이상 R이하일 때 국경선이 열림
-국경선이 열려 인접하게된 국가를 연합국가라 함
-연합 국가의 각 나라의 인구 수는 '연합국가의 인구 수/ 연합국가의 수'가 됨
생각
국경선이 열리는 것까진 일반 BFS 문제와 같겠다 생각함
근데 문제가 잘 이해가 안됐음 구글링해서 이해한 결과
국경선을 여는걸 한번만 하는게 아니라 인구 이동 후에도 또 하고, 또 하고 하는 식인걸 깨달았음!
문제풀이
0.연합국이 없을 때까지 아래 과정을 계속 반복( cnt 개수를 셈 )
1.국경선을 열어줘야함 BFS
1-1.방문표시가 없다면, 큐에 푸쉬
1-2.상하좌우의 나라와의 인구 수 차이가 L이상 R이하이면, 방문표시 + 국경선 넘었다는 표시(areaNum) + 큐에 푸쉬
2.연합국(국경선이 열린 나라)의 인구를 일치 시켜야 함
2-1.국경선이 열려있고 방문표시가 없다면, 인구이동 시작
2-2.큐 두개를 만들어줌(하나는 나라 개수 + 인구 수 구하는 용도/ 다른 하나는 위에서 구한 인구수를 board에 대입할 때 쓰는 용도 )
2-3.상하좌우의 나라가 기준이 되는 나라와 연합국이고, 방문표시가 없다면 방문표시 + 전체 인구수에 인구 수 추가 + 나라 개수 추가 + 큐에 푸쉬
(자꾸 런타임 에러 뜨길래 뭐가 문제인가 했더니, moveQ pop 해줘야하는걸, Q pop 해주고 있었음 ... ㅠㅠ )
코드
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
#define X first
#define Y second
int board[51][51];
int vis[51][51], ckOpen[51][51];
int dx[4] = {0, 1, -1, 0};
int dy[4] = {1, 0, 0, -1};
int L, R, N, cnt=0;
int haveToMove() {
for ( int i = 0; i < N; i++ ) {
for ( int j = 0; j < N; j++ )
if ( ckOpen[i][j] )
return 1;
}
return 0;
}
void movePopulation(int i, int j) {
queue<pair<int, int>> Q;
queue<pair<int, int>> moveQ;
int area = 1;
int areaNum = ckOpen[i][j];
int totalPopulation = board[i][j];
vis[i][j] = 1;
Q.push({i, j});
moveQ.push({i, j});
while (!Q.empty()) {
pair<int, int> cur = Q.front(); Q.pop();
for ( int dir = 0; dir < 4; dir++ ) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if ( nx < 0 || nx >= N || ny < 0 || ny >= N ) continue;
if ( ckOpen[nx][ny] != areaNum || !ckOpen[nx][ny] || vis[nx][ny] ) continue;
vis[nx][ny] = 1;
area++;
totalPopulation += board[nx][ny];
Q.push({nx, ny});
moveQ.push({nx, ny});
}
}
int Population = totalPopulation / area;
while (!moveQ.empty()) {
pair<int, int> cur = moveQ.front(); moveQ.pop(); // 여기서 Q 팝 하니까 오류남 ㅋㅋ
board[cur.X][cur.Y] = Population;
}
}
void OpenLine() {
queue<pair<int, int>> Q;
int areaNum = 0;
for ( int i = 0; i < N; i++ ) {
for ( int j = 0; j < N; j++ ) {
if ( vis[i][j] ) continue;
areaNum++;
vis[i][j] = 1;
Q.push({i,j});
while (!Q.empty()) {
pair<int, int> cur = Q.front(); Q.pop();
for ( int dir = 0; dir < 4; dir++ ) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if ( nx < 0 || nx >= N || ny < 0 || ny >= N ) continue;
if ( vis[nx][ny] ) continue;
int diff = abs(board[cur.X][cur.Y]-board[nx][ny]);
if ( diff < L || diff > R ) continue;
vis[nx][ny] = 1;
ckOpen[cur.X][cur.Y] = ckOpen[nx][ny] = areaNum;
Q.push({nx, ny});
}
}
}
}
}
void Moveto() {
for ( int i = 0; i < N; i++ ) {
for ( int j = 0; j < N; j++ ) {
if ( !ckOpen[i][j] || vis[i][j] ) continue;
movePopulation(i, j);
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> L >> R;
for ( int i = 0; i < N; i++ )
for ( int j = 0; j < N; j++ )
cin >> board[i][j];
while(1) {
memset(vis, 0, sizeof(vis));
memset(ckOpen, 0, sizeof(ckOpen));
OpenLine();
memset(vis, 0, sizeof(vis));
if ( !haveToMove() ) break;
Moveto();
cnt++;
}
cout << cnt;
}
'BOJ_C++_PS' 카테고리의 다른 글
[BOJ/1325번효율적인해킹] c++ / BFS (1) | 2023.10.09 |
---|---|
[BOJ/5014번스타트링크] c++ / BFS (0) | 2023.10.08 |
[BOJ/16953번A->B] c++ / BFS (0) | 2023.10.06 |
[BOJ/1389번케빈베이컨의6단계 법칙] c++ / BFS (0) | 2023.10.05 |
[BOJ/2644번촌수계산] c++ / BFS (1) | 2023.10.04 |