제민
16234 인구 이동 본문
https://www.acmicpc.net/problem/16234
16234번: 인구 이동
N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모
www.acmicpc.net
또다시 삼성의 벽을 느끼게 된 순간이다. 솔직히 문제 자체는 크게 어렵지 않지만 테크닉이 부족해서 시간이 좀 걸렸다.
처음 작성한 코드인데, 80%에서 시간 초과가 걸렸다. 아무리 봐도 답이 나오지 않아 Chat GPT에게 도움을 청했더니 board를 갱신하는 부분을 배열을 하나하나 돌면서 하지 않고, BFS를 사용하면 시간 초과 없이 해결할 수 있었다.
더보기
#include <bits/stdc++.h>
using namespace std;
int N,L,R,idx,days;
int board[53][53];
int vis[53][53];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
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];
bool imigrated=true;
while(imigrated){
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
vis[i][j]=0;
imigrated=false; idx=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(vis[i][j]!=0) continue;
idx++;
queue<pair<int,int>> Q;
Q.push({i,j}); vis[i][j]=idx;
while(!Q.empty()){
auto cur=Q.front(); Q.pop();
for(int dir=0;dir<4;dir++){
int ny=cur.first+dy[dir];
int nx=cur.second+dx[dir];
if(ny<0||nx<0||ny>=N||nx>=N) continue;
int diff=abs(board[cur.first][cur.second]-board[ny][nx]);
if(diff<L||diff>R||vis[ny][nx]!=0) continue;
Q.push({ny,nx}); vis[ny][nx]=idx;
}
}
}
}
for(int num=1;num<=idx;num++){
int sum=0,cnt=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(vis[i][j]==num){
cnt++; sum+=board[i][j];
}
}
}
if(cnt>1){
imigrated=true;
int val=sum/cnt;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(vis[i][j]==num){
board[i][j]=val;
}
}
}
}
}
if(imigrated) days++;
}
cout<<days;
return 0;
}
통과된 코드이다.
#include <bits/stdc++.h>
using namespace std;
int N,L,R,idx,days;
int board[53][53];
int vis[53][53];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
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];
bool imigrated=true;
while(imigrated){
memset(vis, 0, sizeof(vis)); // 방문 여부 배열 초기화
imigrated=false; idx=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(vis[i][j]!=0) continue;
idx++;
queue<pair<int,int>> Q;
Q.push({i,j}); vis[i][j]=idx;
int total_population = board[i][j];
int total_countries = 1;
while(!Q.empty()){
auto cur=Q.front(); Q.pop();
for(int dir=0;dir<4;dir++){
int ny=cur.first+dy[dir];
int nx=cur.second+dx[dir];
if(ny<0||nx<0||ny>=N||nx>=N) continue;
int diff=abs(board[cur.first][cur.second]-board[ny][nx]);
if(diff<L||diff>R||vis[ny][nx]!=0) continue;
Q.push({ny,nx});
vis[ny][nx]=idx;
total_population += board[ny][nx];
total_countries++;
}
}
int new_population = total_population / total_countries;
if (total_countries > 1) { // 인구 이동이 있었으면
imigrated = true;
Q.push({i,j}); // 다시 큐에 넣고
while(!Q.empty()){ // 방문한 곳들의 인구를 모두 변경
auto cur=Q.front(); Q.pop();
board[cur.first][cur.second] = new_population;
for(int dir=0;dir<4;dir++){
int ny=cur.first+dy[dir];
int nx=cur.second+dx[dir];
if(ny<0||nx<0||ny>=N||nx>=N) continue;
if(vis[ny][nx]==idx) {
Q.push({ny,nx}); // 방문 여부를 체크하지 않으면 큐에 넣을 때 여러 번 중복으로 들어갈 수 있음
vis[ny][nx] = -1; // 방문 표시를 함으로써 중복 방문을 방지
}
}
}
}
}
}
if(imigrated) days++;
}
cout<<days;
return 0;
}
'코테연습일지 > 그래프 이론' 카테고리의 다른 글
14923 미로 탈출 (0) | 2024.03.02 |
---|---|
17244 아맞다우산 (비트마스킹) (2) | 2024.02.12 |
16985 Maaaaaaaaaze (2) | 2024.02.08 |
17141 연구소 2 (0) | 2024.02.07 |
14502 연구소 (0) | 2024.02.07 |