본문 바로가기
알고리즘/그래프

[java 백준] 골드 5/ 16234번 인구이동

by Meaning_ 2022. 7. 5.
728x90
반응형

https://www.acmicpc.net/problem/16234

 

16234번: 인구 이동

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

www.acmicpc.net

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
 
class Main{
 
 
    public static int n;
    public static int l;
    public static int r;
    public static int arr[][];
    public static boolean visit[][];
    public static int dirX[]={-1,1,0,0};
    public static int dirY[]={0,0,-1,1};
    public static int ans=0;
 
    public static class Node{
        int x,y;
        public Node(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
 
    public static boolean check(int x,int y,int nx,int ny){
 
        int sub=Math.abs(arr[x][y]-arr[nx][ny]);
        if(sub>=l&&sub<=r){
            return true;
        }
 
 
        return false;
    }
 
 
 
    public static int move(){
        int unionCount=0;
        int unionSize=0;
 
        //탐색
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(!visit[i][j]){
 
 
                    Queue<Node> queue=new LinkedList<Node>();
                    ArrayList<Node>list=new ArrayList<Node>();
                    queue.add(new Node(i,j));
                    list.add(new Node(i,j));
                    unionCount=arr[i][j];
                    visit[i][j]=true;//중요!
 
                    while(!queue.isEmpty()){
                        Node node=queue.poll();
                        for(int s=0;s<4;s++){
                            int nx=node.x+dirX[s];
                            int ny=node.y+dirY[s];
                            if(nx>=0&&nx<n&&ny>=0&&ny<n){
                                if(!visit[nx][ny]&&check(node.x,node.y,nx,ny)){
                                    queue.add(new Node(nx,ny));
                                    list.add(new Node(nx,ny));
                                    visit[nx][ny]=true;
                                    unionSize++;
                                    unionCount+=arr[nx][ny];
                                }
                            }
                        }
                    }
                    //평균값으로 채워주기
                    if(unionSize>0){
                        int avg=unionCount/list.size();
                        for(Node node:list){
                            arr[node.x][node.y]=avg;
                        }
                    }
                }
            }
        }
 
 
 
        //다 false로 바꿔주기
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                visit[i][j]=false;
            }
        }
 
 
        return unionSize;
 
    }
 
    public static void main(String[]args) throws IOException {
        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());
        arr=new int[n][n];
        visit=new boolean[n][n];
        for(int i=0;i<n;i++){
            st=new StringTokenizer(br.readLine());
            for(int j=0;j<n;j++){
                arr[i][j]=Integer.parseInt(st.nextToken());
            }
        }
 
 
 
        boolean isFlag=true;
        while(isFlag){
            if(move()==0){
                isFlag=false;
            }else{
                ans++;
            }
        }
 
        System.out.println(ans);
 
 
 
 
    }
}
cs

 

 

생각의 절차가 3가지가 필요한데

 

1. 인구이동 횟수를 while로 구현 (더이상 이동 못할때까지 반복문 돌려주기)

2. bfs를 통해 인접하고 범위에 들어오는 숫자의 위치를 queue,arraylist에 넣기

3. 평균을 구해서 큐에 있는 숫자들의 위치에 평균값을 넣어주기

 

이다.

 

특히 인구이동횟수는 move함수에서 BFS를 돌면서 unionSize 값이  0이면 더이상 탐색할게 없다는 것이니 반복문을 끊어주면 되는것을 생각해줘야 한다.

그리고 visit잘 확인해야한다. 이거때문에 재귀가 깊어진다. 

728x90
반응형

댓글