알고리즘/백준
16234번 : 인구 이동 (JAVA)
가든_
2022. 10. 9. 23:17
LOGIC
- 모든 맵의 위치에서
- 방문하지 않은 나라라면
- dfs로 주위 연합 찾기
- 방문하지 않았고 범위 안에 있는 옆 나라라면, 두 나라 사이의 갭을 구하기
- 갭이 범위 안에 있다면, 해당 나라 큐와 연합 리스트에 집어 넣기
- 큐에 남은 나라가 없다면
- 연합이 있었다면 연합의 인구 수 평균을 구해서 나눠주기
- 모든 배열을 체크 했을 때 까지 반복
CODE
package baekjoon16234;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main2
{
static class Country
{
int posX;
int posY;
public Country(int posX, int posY) {
super();
this.posX = posX;
this.posY = posY;
}
}
static int direction[][] = {{-1, 0},{1, 0},{0, -1},{0, 1}};
static boolean isVisited[][];
static int map[][];
static int N, min, max, answer = 0;
static boolean isUnion = false;
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());//1 ≤ N ≤ 50
min = Integer.parseInt(st.nextToken());//1 ≤ L ≤ R ≤ 100
max = Integer.parseInt(st.nextToken());//1 ≤ L ≤ R ≤ 100
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());
}
}
//연합이 있을때만 반복
while(true)
{
isUnion = false;
isVisited = new boolean[N][N];
for(int i = 0; i<N; i++)
{
for(int j = 0; j<N; j++)
{
if(!isVisited[i][j])//방문하지 않았다면
{
bfs(new Country(i, j));//i, j 주변 탐색
}
}
}
if(isUnion) answer++; //연합이 있다면 답에 1더하기
else //연합이 없다면
{
System.out.println(answer); //답 출력
break;//반복문 나가기
}
}
}
private static void bfs(Country startCountry)
{
Queue<Country> queue = new LinkedList<>();//bfs 탐색을 기다리는 큐
List<Country> union = new ArrayList<>();//연합의 정보를 담고있는 리스트
queue.offer(startCountry);//시작 나라 삽입
union.add(startCountry);//시작 나라 삽입
//방문 체크
isVisited[startCountry.posX][startCountry.posY] = true;
int sum = map[startCountry.posX][startCountry.posY];//연합 총 인구수에 인구수 더하기
int count = 1;//나라 수 세기
boolean isCurrentUnion = false;//연합 유무 체크
while(!queue.isEmpty())
{
Country currentCountry = queue.poll();
for(int i = 0; i<direction.length; i++)
{
int nextX = currentCountry.posX + direction[i][0];
int nextY = currentCountry.posY + direction[i][1];
//범위를 벗어났거나, 방문한적 있으면 반복문 나가기
if(nextX<0 || nextX>=N || nextY<0 || nextY>= N || isVisited[nextX][nextY]) continue;
//현재 나라와 현재 나라와 인접하고 있는 나라 인구 차이 계산
int gap = Math.abs(map[currentCountry.posX][currentCountry.posY] - map[nextX][nextY]);
//인구 차가 범위 안이라면
if(gap>=min&&gap<=max)
{
isCurrentUnion = true;//연합 유무 체크
isVisited[nextX][nextY] = true;//방문 체크
queue.offer(new Country(nextX, nextY));//큐에 추가
union.add(new Country(nextX, nextY));//연합 리스트에 추가
sum+=map[nextX][nextY];//연합 총 인구수에 인구수 더하기
count++;//연합 수 더하기
}
}
}
//연합이 만들어졌다면
if(isCurrentUnion)
{
isUnion = true;//연합 만들어졌다고 알리기
int value = sum/count;//평균 값 구하기
for(int i = 0; i<union.size(); i++)
{
int x = union.get(i).posX;
int y = union.get(i).posY;
map[x][y] = value;//맵 갱신
}
union = new ArrayList<>();//연합 정보 초기화
}
}
}