[삼성기출]백준16234 - 인구이동

 
by 박신종

이 문제는 bfs로 인구 이동여부를 파악하여 풀었습니다.


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

public class Main16234_인구이동 {
	
	static int N,L,R;
	static int[][] map;
	static boolean[][] visit;
	static int[][] dir = // 우,하,좌,상; 
    
	static boolean check(int x, int y) {
		if(x>=0 && x<map.length && y>=0 && y<map[x].length)
			return true;
		else return false;
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] input = br.readLine().trim().split(" ");
		N = Integer.parseInt(input[0]);
		L = Integer.parseInt(input[1]);
		R = Integer.parseInt(input[2]);
		map = new int[N][N];
		for(int i=0; i<N; i++) {
			String[] str = br.readLine().trim().split(" ");
			for(int j=0; j<N; j++) {
				map[i][j] = Integer.parseInt(str[j]);
			}
		}
		int res = 0;
		/*
		 * 최대 2000번까지 이동체크.
		 */
		for(int i=1; i<=2000; i++) {
			visit = new boolean[N][N];
			if(!move()) { // 이동할 수 없으면 이전 값 리턴. 
				res = i-1;
				break;
			}
		}
		System.out.println(res);
	}
	
	
	public static boolean move() {
		int cnt = 0;
		for(int i=0; i<map.length; i++) {
			for(int j=0; j<map[i].length; j++) {
				if(!visit[i][j] && union(i,j)) cnt++;
			}
		}
		return cnt>0?true:false; // 한번이라도 이동했으면 true
	}
	static class Pos{
		int x,y;

		public Pos(int x, int y) {
			this.x = x;
			this.y = y;
		}

		@Override
		public String toString() {
			return "[" + x + "," + y + "]";
		}
		
	}
	public static boolean union(int x, int y) {
		/*
		 * 시작점으로 부터 bfs로 연합하고 인구수 나누기.
		 */
		boolean flag = false;
		Queue<Pos> qu = new LinkedList<>();
		List<Pos> list = new ArrayList<>();
		Pos p = new Pos(x,y);
		qu.add(p);
		list.add(p);
		visit[p.x][p.y]=true;
		int dx,dy;
		int sum = 0;
		Pos tmp = null;
		while(!qu.isEmpty()) {
			p = qu.poll();
			sum += map[p.x][p.y];
			for(int d=0; d<4; d++) {
				dx = p.x + dir[d][0];
				dy = p.y + dir[d][1];
				if(check(dx,dy) && !visit[dx][dy] && checkDistance(p.x,p.y,dx,dy)) {
					tmp = new Pos(dx,dy);
					qu.add(tmp);
					list.add(tmp);
					visit[dx][dy]=true;
					flag = true;
				}
			}
		}
		
		// 우리 국가 이외에 다른 국가도 있으면 계산.
		if(list.size()>1) {
			int dis = sum/list.size();
			for(int i=0; i<list.size(); i++) {
				map[list.get(i).x][list.get(i).y] = dis;
			}
		}
		return flag;
	}
	
	// 인접한 국가와의 인구차이로 연합할 수 있는지 체크.
	static boolean checkDistance(int x1, int y1, int x2, int y2) {
		int dis = Math.abs(map[x1][y1] - map[x2][y2]);
		if(dis >=L && dis <= R)
			return true;
		else return false;
	}
	
	public static void print() {
		for(int i=0; i<map.length; i++) {
			for(int j=0; j<map[i].length; j++)
				System.out.print(map[i][j]+" ");
			System.out.println();
		}
		System.out.println("======================");
	}
}