danbibibi
article thumbnail

문제

문제 바로가기> BOJ 16234번: 인구이동

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모

www.acmicpc.net

 

풀이

문제의 요구사항을 구현해주면 되는 간단한 문제였다.

 

1. 연합을 구하기 위해 그래프 탐색 (DFS or BFS) 진행

2. 연합의 크기 > 1 인 경우, 인구 이동

    연합의 크기 < 1 인경우, break ; 정답 출력

 

크게 위와 같은 2가지 과정으로 이루어지는데,

연합을 구하기 위해 DFS를 사용했을 때가 BFS를 사용했을 때 보다 시간이 훨씬 줄어들었다.

 

그 이유를 찾아보니 ...

DFS함수보다 BFS가 메모리와 시간이 더 필요로 한다고 한다.

BFS를 진행할 때, queue에서 넣고 꺼내고 복사하는 과정이 느리다고 ... !

DFS는 어떻게든 찾기만 하면 될 때 쓰고, BFS는 탐색 시 이동 횟수가 최소인 것을 찾을 때 쓰는 느낌이라고,, 했다 ㅎㅎ

 

C++

#include<iostream>
#include<cstring>
#include<vector>
#define MAX 51
using namespace std;

int total;
int N, L, R;
int map[MAX][MAX];
bool visited[MAX][MAX];
int dy[] = {-1, 1, 0, 0};
int dx[] = {0, 0, -1, 1};
vector<pair<int, int>> pos;

void input(){
    cin >> N >> L >> R;
    for(int i=0; i<N; i++){
        for(int j=0; j<N; j++) cin >> map[i][j];
    }
}

void make_union(int y, int x){
    visited[y][x] = true;
    pos.push_back({y, x});

    for(int d=0; d<4; d++){
        int ny = y+dy[d];
        int nx = x+dx[d];
        if(ny<0 || ny>=N || nx<0 || nx>=N || visited[ny][nx]) continue; // 범위를 벗어나는 경우, 이미 방문한 경우
        int diff = abs(map[y][x]-map[ny][nx]); // 국경선을 공유하는 두 나라의 인구 차
        if(L<=diff && diff<=R){ // L명 이상, R명 이하인 경우
            total+=map[ny][nx];
            make_union(ny, nx);
        }
    }
}

void solution(){ // 인구 이동이 며칠 동안 발생하는지

    int ans = 0;
    while(true){
        
        memset(visited, false, sizeof(visited)); // init
        
        bool ismove = false;
        for(int i=0; i<N; i++){
            for(int j=0; j<N; j++){
                if(visited[i][j]) continue;
                pos.clear();
                total = map[i][j];
                make_union(i, j); // 연합을 이루고

                if(pos.size() == 1) continue;
                
                // 인구 이동
                ismove = true;
                int avg = total/(int)pos.size();
                for(int p=0; p<(int)pos.size(); p++){
                    int y = pos[p].first;
                    int x = pos[p].second;
                    map[y][x] = avg;
                }
            }
        }
        if(!ismove) break; // 인구 이동이 발생하지 않는 경우
        ans++; // 인구 이동이 발생한 경우
    } 
    cout << ans;
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    input();
    solution();
}

 

Java

import java.io.*;
import java.util.*;

public class Main {
	
	private static int dy[] = {0, -1, 0, 1};
	private static int dx[] = {1, 0, -1, 0};
	private static int N, L, R, total;
	
	private static int[][] map;
	private static boolean[][] visited;
	static List<int[]> pos = new ArrayList<int[]>();

	public static void main(String[] args) throws Exception {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		L = Integer.parseInt(st.nextToken());
		R = Integer.parseInt(st.nextToken());
		
		map = new int[N][N];
		
		for(int i=0; i<N; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0; j<N; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		solution();
	}

	private static void solution() {
	    int ans = 0;
	    while(true){
	        
	        visited = new boolean[N][N];
	        
	        boolean ismove = false;
	        for(int i=0; i<N; i++){
	            for(int j=0; j<N; j++){
	                if(visited[i][j]) continue;
	                pos = new ArrayList<int[]>();
	                total = map[i][j];
	                make_union(i, j); // 연합을 이루고

	                if(pos.size() == 1) continue;
	                
	                // 인구 이동
	                ismove = true;
	                int avg = total/(int)pos.size();
	                for(int p=0; p<(int)pos.size(); p++){
	                    int y = pos.get(p)[0];
	                    int x = pos.get(p)[1];
	                    map[y][x] = avg;
	                }
	            }
	        }
	        if(!ismove) break; // 인구 이동이 발생하지 않는 경우
	        ans++; // 인구 이동이 발생한 경우
	    } 
	    System.out.println(ans);
	}

	private static void make_union(int y, int x){
	    visited[y][x] = true;
	    pos.add(new int[] {y,x});

	    for(int d=0; d<4; d++){
	        int ny = y+dy[d];
	        int nx = x+dx[d];
	        if(ny<0 || ny>=N || nx<0 || nx>=N || visited[ny][nx]) continue; // 범위를 벗어나는 경우, 이미 방문한 경우
	        int diff = Math.abs(map[y][x]-map[ny][nx]); // 국경선을 공유하는 두 나라의 인구 차
	        if(L<=diff && diff<=R){ // L명 이상, R명 이하인 경우
	            total+=map[ny][nx];
	            make_union(ny, nx);
	        }
	    }
	}

}

'문제 풀이 > SW 역량 테스트' 카테고리의 다른 글

BOJ 17142번: 연구소 3  (0) 2023.02.01
BOJ 16235번: 나무 재테크  (0) 2023.01.31
BOJ 15685번: 드래곤 커브  (0) 2023.01.29
BOJ 15683번: 감시  (0) 2023.01.26
BOJ 14501번: 퇴사  (0) 2023.01.24
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로