문제 풀이 및 개발 공간

[백준] 16234번 인구이동 (gold 4 본문

백준공부/java

[백준] 16234번 인구이동 (gold 4

gomduri43 2024. 4. 5. 11:45

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

class Point{
    int x;
    int y;
    public Point(int x, int y){
        this.x=x;
        this.y=y;
    }
}
public class Main{
    static int[] numx={-1,1,0,0};
    static int[] numy={0,0,-1,1};
    static int n;
    static int l;
    static int r;
    //인구연합담을 큐
    static Queue<Point> unit=new LinkedList<>();
    //인구수를 담을 맵
    static int[][] map;
    //방문정보 저장
    static boolean[][] visit;
    //끝났는지 파악
    static boolean finish=false;
    public static void main(String[] args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st=new StringTokenizer(br.readLine());

        n=Integer.valueOf(st.nextToken());
        l=Integer.valueOf(st.nextToken());
        r=Integer.valueOf(st.nextToken());

        map=new int[n+1][n+1];

        //인구수저장
        for(int i=1; i<=n; i++){
            st=new StringTokenizer(br.readLine());
            for(int j=1; j<=n; j++){
                map[i][j]=Integer.valueOf(st.nextToken());
            }
        }

        int time=0;

        while(true){
            select();
            if(finish){
                break;
            }
            time++;
        }
        bw.write(time+"");
        bw.flush();
    }

    //맵에서 방문안된 점들을 기준으로해서 연합결성여부
    public static void select(){
        visit=new boolean[n+1][n+1];
        //select진행마다 finish를 true로 설정하고,
        //연합이 결성되어 있는 경우 다시 false로 돌림.
        finish=true;
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                if(!visit[i][j]){
                    makeUnit(j,i);
                }
            }
        }
    }

    //지정된 점으로부터 연합결성
    public static void makeUnit(int x, int y){
        Queue<Point> que=new LinkedList<>();
        visit[y][x]=true;
        que.offer(new Point(x,y));
        unit.offer(new Point(x,y));
        int sum=map[y][x];
        while(!que.isEmpty()){
            Point temp=que.poll();
            int min=map[temp.y][temp.x];
            for(int i=0; i<4; i++){
                int tx=temp.x+numx[i];
                int ty=temp.y+numy[i];

                if(tx<1 || tx>n || ty<1 || ty>n || visit[ty][tx] || Math.abs(min-map[ty][tx])<l || Math.abs(min-map[ty][tx])>r ){
                    continue;
                }
                visit[ty][tx]=true;
                sum+=map[ty][tx];
                que.offer(new Point(tx, ty));
                unit.offer(new Point(tx,ty));
            }
        }
        setting(sum);
    }
    //결성된 연합 map에서 숫자 재설정
    public static void setting(int sum){
        if(unit.size()==1){
            unit.clear();
            return;
        }
        //아직 끝난게 아님. 인구연합이 발생해있음
        finish=false;
        int num=sum/unit.size();
        while(!unit.isEmpty()){
            Point temp=unit.poll();
            map[temp.y][temp.x]=num;
        }
    }
}