[백준/JAVA] 16234번: 인구 이동
📖 문제
16234번: 인구 이동
N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모
www.acmicpc.net
💡 풀이 방식
• BFS
인구 이동이 가능하지 않을 때까지 인구 이동을 진행한다. (while문)→ 완전탐색을 통해 격자 내의 모든 점에 대해 인구 이동이 가능한지 확인한다. (move 메소드)
→ 모든 점에 대해 4방향 탐색하며인접한 나라와 국경선이 열려있다면, 해당 나라에서 이동하며 연합한다. (BFS)
- 이동 및 연합 가능한 나라는 방문한 적 없고, 두 나라 간 인구 수 차이가 L이상 R이하인 나라여야 한다.
- 조건을 만족하는 인접한 나라로 이동하며 방문 처리하고, 리스트에 연합한 나라의 r,c좌표와 해당 칸의 인구 수를 저장한다.
- 연합한 국가가 2개 이상인 경우, 연합한 나라의 좌표와 인구수를 저장한 리스트를 돌며 (연합의 인구수) / (연합을 이루고 있는 칸의 개수)를 계산하고, 이 값으로 해당 칸들의 값을 갱신한다.
→ 인구 이동이 가능하지 않다면, 함수를 종료하고 여태까지 구한 인구 이동 횟수를 출력하고 끝낸다.
🔺 코드
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
|
import java.util.*;
import java.io.*;
public class Main {
static int[] dr = {-1,1,0,0};
static int[] dc = {0,0,-1,1};
static int N,L,R;
static int[][] map;
static boolean[][] visited;
static int cnt = 0;
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()); // 인구 차이 최대
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());
}
}
visited = new boolean[N][N];
while(move()) { // 인구 이동이 없을 때까지 인구 이동
cnt++;
visited = new boolean[N][N]; // = 연합 해체
}
System.out.println(cnt);
}
// 인구 이동 가능한지 판별하는 메서드 (이동 가능하면 이동시킴)
private static boolean move() {
boolean ok = false; // 이동 가능 여부
for(int i = 0 ; i < N ; i++) {
for(int j = 0 ; j < N ; j++) {
if(!visited[i][j]) {
visited[i][j] = true; // 방문 처리
boolean opened = false; // 국경선 열렸는지 여부
for(int d = 0 ; d < 4 ; d++) { // 4방향 탐색
int nr = i + dr[d];
int nc = j + dc[d];
// 격자 범위 내에 있고, 두 나라 간 인구 차이가 L과 R사이라면
if(inRange(nx,ny) && betweenLR(i, j, nr, nc)) {
opened = true; // 국경선 열림
ok = true; // 이동 가능
}
}
if(opened) { // 국경선이 열렸다면, 이동하며 연합
bfs(i, j);
}
}
}
}
return ok;
}
// 인접한 국경선이 열린 나라끼리 이동하며 연합하는 메서드
private static void bfs(int x, int y) {
Queue<int[]> q = new ArrayDeque<>();
q.add(new int[] {x, y});
List<int[]> list = new ArrayList<>(); // 연합한 나라의 x,y 좌표 & 인구 수 저장 리스트
list.add(new int[] {x, y, map[x][y]});
while(!q.isEmpty()) {
int[] now = q.poll();
for(int d = 0 ; d < 4 ; d++) {
int nx = now[0] + dr[d];
int ny = now[1] + dc[d];
// 방문한 적 없고, 이동 가능한 칸이라면 이동
if(inRange(nx, ny) && !visited[nx][ny] && betweenLR(now[0], now[1], nx, ny)) {
visited[nx][ny] = true;
list.add(new int[] {nx, ny, map[nx][ny]});
q.add(new int[]{nx, ny});
}
}
}
if(list.size() == 1) return;
// 연합 국가가 2개 이상인 경우, 연합 이루는 각 칸의 인구 수 갱신
int total = 0;
for(int[] arr : list) {
total += arr[2];
}
total /= list.size();
for(int[] arr : list) {
map[arr[0]][arr[1]] = total;
}
}
// 두 나라 간 인구 차이가 L이상 R이하인지 확인하는 메서드
private static boolean betweenLR(int a, int b, int c, int d) {
int diff = Math.abs(map[a][b] - map[c][d]);
return L <= diff && diff <= R;
}
private static boolean inRange(int r, int c) {
return 0 <= r && r < N && 0 <= c && c < N;
}
}
|
cs |
➕ 다른 풀이 방식
셋 다 비슷하긴 한데 무려 20줄이나 짧다!!
[다른 점]
- move 메소드에서 굳이 4방향 탐색을 하지 않고, 방문하지 않은 점에서 바로 BFS 수행해도 된다.
- 방문 배열 초기화 위치를 앞쪽으로 뒀다.
[백준]16234: 인구 이동 - JAVA
문제 https://www.acmicpc.net/problem/16234 16234번: 인구 이동 N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고
moonsbeen.tistory.com
[백준] 16234_인구이동 (JAVA)
1. 문제 https://www.acmicpc.net/problem/16234 16234번: 인구 이동 N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살
sumdev.tistory.com
[백준 16234] - 인구이동(JAVA)
[문제] 출처 - https://www.acmicpc.net/problem/16234 16234번: 인구 이동 N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명
dding9code.tistory.com
💦 어려웠던 점
- 푸는 데 40분... 오류 잡는 데 20분... 처음에 너무 함수 분리한답시고 다른 방향으로 문제 풀고 있었음,,, 헤매는 시간을 줄이자,,,
1회독 | 2회독 | 3회독 | 4회독 | 5회독 |
V |