문제
https://www.acmicpc.net/problem/16234
풀이(24분)
import java.io.*;
import java.util.*;
class Main {
static int n, l, r, count, answer;
static int[][] map;
static boolean[][] visited;
static List<Point> points = new ArrayList<>();
static Queue<Point> queue = new LinkedList<>();
static int[] dx = new int[]{0, 0, -1, 1};
static int[] dy = new int[]{-1, 1, 0, 0};
static boolean flag = false;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
l = Integer.parseInt(st.nextToken());
r = Integer.parseInt(st.nextToken());
map = new int[n][n];
visited = new boolean[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());
}
}
do{
flag = false;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(visited[i][j]){ // 이미 체크했다면 패스
continue;
}
visited[i][j] = true; // 방문 체크
points.clear(); // points 배열 초기화
points.add(new Point(i, j));
queue.add(new Point(i, j));
count = map[i][j]; // count 값 초기화
bfs(); // bfs 시작
if(points.size() != 1){ // points의 사이즈가 1이라면 국경이 개방된 적이 없음
flag = true;
}
for(Point p : points){
map[p.row][p.col] = count / points.size(); // 소숫점 절삭
}
}
}
for(int i = 0; i < n; i++){
Arrays.fill(visited[i], false); // 방문 배열 초기화
}
if(flag){ // 한 국가라도 이동한 적이 있다면 정답 추가
answer++;
}
}while(flag);
System.out.println(answer);
}
static void bfs(){
while(!queue.isEmpty()){
Point p = queue.poll();
int curRow = p.row;
int curCol = p.col;
for(int i = 0; i < 4; i++){
int nextRow = curRow + dx[i];
int nextCol = curCol + dy[i];
if(!isInBounds(nextRow, nextCol)){ // 범위 안에 있는지
continue;
}
if(visited[nextRow][nextCol]){ // 방문한 적이 있는지
continue;
}
int diff = Math.abs(map[curRow][curCol] - map[nextRow][nextCol]); // 두 국가 간의 인원 수 차이
if(diff >= l && diff <= r){ // 차이가 범위 안에 들어온다면
points.add(new Point(nextRow, nextCol));
count += map[nextRow][nextCol];
visited[nextRow][nextCol] = true;
queue.add(new Point(nextRow, nextCol));
}
}
}
}
static class Point{
int row, col;
public Point(int row, int col) {
this.row = row;
this.col = col;
}
}
private static boolean isInBounds(int x, int y) {
return x >= 0 && x < n && y >= 0 && y < n;
}
}
문제 풀이 전략
우선 국경을 확인한다. 이 때 union-find를 사용할까 했지만 굳이 복잡하게 쓰기보다는 방문 배열을 통해 중복 체크하지만 않게 하는 것으로 했다.
1. 하나의 점에 대해 방문을 확인한 뒤, 국경을 모두 확인한다.
2. 국경이 확인되면 개방될 수 있는지 확인한다.
2-1. 국경이 개방되었다면 개방된 국가에 대해 인구를 통합한다.
2-2. 개방되지 않았다면 방문 체크만 한 뒤 넘어간다.
3. 모든 점에 대해 탐색을 진행하며 국경이 한번이라도 개방된 경우가 있을 때까지만 진행한다.
'문제 풀이 > 백준' 카테고리의 다른 글
[백준] 9019번. DSLR(JAVA) (0) | 2025.05.24 |
---|---|
[백준] 1922번. 네트워크 연결(JAVA) (0) | 2025.05.24 |
[백준] 17142번. 연구소 3(JAVA) (0) | 2025.05.23 |
[백준] 16235번. 나무 재테크(JAVA) (0) | 2025.04.25 |
[백준] 11779번. 최소비용 구하기 2(JAVA) (1) | 2025.04.24 |