문제
2차원 배열에 국가별 인구 수가 주어져있을 때 인접한 국가의 인구수가 주어진 범위 내에 있으면 국경을 열어 인구이동을 하여 1/N인구로 만드는 작업을 반복할 때, 인구이동이 몇 번 일어나는 지 알아내는 문제
https://www.acmicpc.net/problem/16234
접근방법
BFS를 이용해 인접한 영역을 확인하고 인구이동을 한다.
인구이동을 한 국가는
booelan moved[][]
를 이용해 표시한다.한 번 전체 국가가 인구이동을 한 뒤에는 이동 수를 증가시키고
moved[][]
를 초기화 해준다.
BFS를 이용해 인접한 영역 확인하기
2개의 boolean 2차원 배열을 사용해주었다.
1) BFS 체크용 boolean 배열 시간이 초과되지 않도록 이미 방문한 배열 체크
2) 인구이동한 국가 확인용 boolean 배열
moved[][]
인접한 배열을 큐에 넣을지 결정하기 위해서는 다음의 네가지를 확인해주어야 한다.
1) 배열의 범위를 벗어났는가
이 경우는 애초에 배열을 2칸씩 크게 만들어서, 해당 원소의 값이 0인지 여부만 확인해주면 된다.
2) 아직 인구이동이 되지 않은 지역인가
moved 배열 확인
3) BFS가 이미 방문한 원소인가
check 배열 확인
4) 인구차이가 범위 내에 있는가
위 네가지를 확인한 뒤에 큐에 넣어준다.
해당 큐를 이용하여 인구 수를 설정해주고, moved를 함께 체크한다.
인접값을 확인하기 전부터 미리 하나는 큐에 들어가므로, 큐의 개수가 1개 초과일 경우가 인구이동이 일어난 경우이다.
인구이동이 일어난 국가들의 인구 수를 변경해주기 위해, 큐에서 빼낸 좌표들은 다시 새로운 큐(queue_tmp)에 넣어준다.
소스코드
import java.util.*;
import java.io.*;
public class Main{
static int[] dx = {1, -1, 0, 0};
static int[] dy = {0, 0, 1, -1};
static int N;
static int minGap;
static int maxGap;
static int[][] map;
static boolean[][] moved;
static boolean isQuit;
static class Pos{
int x; int y;
public Pos(int x, int y) {this.x= x; this.y = y;}
}
static void BFS(int x, int y){
boolean check[][] = new boolean[N+2][N+2];
Queue<Pos> queue = new LinkedList();
Queue<Pos> queue_tmp = new LinkedList();
queue.offer(new Pos(x, y));
int sum = 0;
while(!queue.isEmpty()) {
Pos cur_pos = queue.poll();
check[cur_pos.x][cur_pos.y] = true;
sum += map[cur_pos.x][cur_pos.y];
queue_tmp.offer(new Pos(cur_pos.x, cur_pos.y));
for (int i = 0; i < 4; i++) {
Pos next_pos = new Pos(cur_pos.x + dx[i], cur_pos.y + dy[i]);
int gap = Math.abs(map[cur_pos.x][cur_pos.y] - map[next_pos.x][next_pos.y]);
if( map[next_pos.x][next_pos.y] != 0 // 경계가 아니면서
&& !moved[next_pos.x][next_pos.y] // 아직 인구이동이 되지 않은 지역이면서
&& !check[next_pos.x][next_pos.y] // <<BFS방문체크>>
&& gap >= minGap && gap <= maxGap){ // 인구 차이가 범위 내인 경우
queue.offer(next_pos); // 큐에 넣어준다.
check[next_pos.x][next_pos.y] = true;
}
}
}
// 인구이동이 일어난 경우
if(queue_tmp.size() != 1){
isQuit = false;
int value = sum / queue_tmp.size();
while(!queue_tmp.isEmpty()){
Pos pos = queue_tmp.poll();
map[pos.x][pos.y] = value;
moved[pos.x][pos.y] = true;
}
}
}
public static void main(String[] args) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] input = in.readLine().split(" ");
N = Integer.parseInt(input[0]);
minGap = Integer.parseInt(input[1]);
maxGap = Integer.parseInt(input[2]);
map = new int[N+2][N+2];
moved = new boolean[N+2][N+2];
for(int i=1; i<=N; i++){
String line[] = in.readLine().split(" ");
for(int j=1; j<=N; j++)
map[i][j] = Integer.parseInt(line[j-1]);
}
int result = 0;
while(true){
isQuit = true;
for(int i=1; i<=N ;i++)
for (int j = 1; j <= N; j++)
if (!moved[i][j])
BFS(i, j);
if(!isQuit){
++result;
// 인구이동여부 초기화
for(int i=1; i<=N; i++)
for(int j=1; j<=N; j++)
moved[i][j] = false;
} else{ // 인구이동 하나도 없을 시 종료
break;
}
}
System.out.println(result);
}
}
'알고리즘' 카테고리의 다른 글
[JAVA] 백준 1120 : 문자열 (0) | 2019.01.13 |
---|---|
백준15686 : 치킨 배달 (0) | 2018.11.23 |
백준15684 : 사다리 조작 (0) | 2018.11.21 |
백준14889 : 스타트와 링크 (0) | 2018.11.16 |
[JAVA] 백준 3055 : 탈출 (0) | 2018.09.27 |