티스토리 뷰
문제에 나와있는 대로 구현하면 풀리는 정직한 시뮬레이션 문제
16234번: 인구 이동
N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모
www.acmicpc.net
풀이
처음에 문제가 애매하다는 생각이 들었다. 이차원배열을 map
이라 하면 map
에 따로 떨어진 두 집단이 있을경우 이걸 각각 인구 이동횟수로 세야하는지 아니면 한 round당 횟수로 해야하는지 몰랐다.
그래서 질문게시판을 참고하니 후자인 한 round당으로 세는게 맞았다. 즉, map
에서 인구 이동이 가능한 집단이 여러 개가 있어도 한 번으로 치는 것이다.
우선 BFS를 해야하므로 방문체크 배열을 두었다. 인구 이동이 더이상 없는 경우를 알려주는 boolean flag
변수를 두었다. 인구 이동 결과를 저장할 임시 이차원 배열을 두는데, 인구 수의 범위가 0~100
이므로 Arrays.fill
method를 이용하여 -1로 초기화 해놓는다.
인구 이동을 할 후보군 좌표 저장을 위해서 BFS용 큐 말고 candidate
라는 큐를 하나 더 두었다. 이 candidate
큐에 element를 추가할 때 마다 해당 좌표의 인구 수를 미리 더해서 합을 저장한다.
처음에 자기 자신을 큐에 포함하기 때문에 candidate
큐의 크기가 2 이상이라면 인구 이동이 가능하므로 임시로 만든 이차원 배열에 이동된 인구 수를 저장한다. 이때 이동이 일어났다면 flag
변수값을 true
로 설정한다.
모든 map
좌표 탐색이 끝난 이후 flag
값이 false
일 경우 while
문을 break
하고 최종 인구이동 횟수를 출력한다.
그렇지 않으면 임시로 만든 이차원 배열 값을 원래 map
에 옮긴다.
Logic
while
문 시작시flag, visited, temp
를 초기화한다.- 이중
for
문을 돌며 방문하지 않은 곳이라면 BFS 탐색을 시작한다.sum
값은 시작좌표 인구값으로 초기화한다.solve()
: 현재 좌표값과 다음으로 갈 수 있는 좌표값 차이가\[L, R\]
이라면 BFS 큐 뿐만 아니라candidate
큐에도 저장한다. 이때sum
값에 다음 좌표값을 더해준다.movePeople()
: BFS탐색 이후candidate
큐 크기가 2 이상이면flag = true
로 표시하고 임시배열인temp
에 인구이동 결과값을 저장한다. candidate 큐는 비워준다.migrate()
:flag = true
이면map
을temp
값으로 바꾼다. 만약temp
값이 -1일땐 인구 이동이 일어나지 않은 것이므로 바꾸지 않는다.
flag == false
이면 인구이동이 일어나지 않았다는 뜻이므로while
문을break
한다.- 인구이동 횟수를 출력한다.
코드
import java.io.*;
import java.util.*;
public class Main {
static int N, L, R, move, sum;
static int[] pos_x = { 1, 0, -1, 0 };
static int[] pos_y = { 0, 1, 0, -1 };
static int[][] map, temp;
static boolean[][] visited;
static boolean flag;
static Queue<Coord> candidate = new LinkedList<>();
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 + 2][N + 2];
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) {
flag = false;
visited = new boolean[N + 2][N + 2];
temp = new int[N + 2][N + 2];
for (int[] row : temp)
Arrays.fill(row, -1);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if(!visited[i][j]) {
visited[i][j] = true;
solve(i, j);
if (candidate.size() > 1) {
flag = true;
movePeople();
}
candidate.clear();
}
}
}
if (!flag) break;
migrate();
move++;
}
System.out.println(move);
br.close();
}
public static void movePeople() {
int avg = sum / candidate.size();
while(!candidate.isEmpty()) {
int x = candidate.peek().x;
int y = candidate.peek().y;
candidate.poll();
temp[x][y] = avg;
}
}
public static void migrate() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (temp[i][j] == -1) continue;
map[i][j] = temp[i][j];
}
}
}
public static void solve(int i, int j) {
Queue<Coord> q = new LinkedList<>();
q.offer(new Coord(i, j));
candidate.offer(new Coord(i, j));
sum = map[i][j];
while(!q.isEmpty()) {
int x = q.peek().x;
int y = q.peek().y;
q.poll();
for (int d = 0; d < 4; d++) {
int nx = x + pos_x[d];
int ny = y + pos_y[d];
if (nx < 0 || nx >= N || ny < 0 || ny >= N || visited[nx][ny]) continue;
int diff = Math.abs(map[nx][ny] - map[x][y]);
if (diff < L || diff > R) continue;
visited[nx][ny] = true;
q.offer(new Coord(nx, ny));
sum += map[nx][ny];
candidate.offer(new Coord(nx, ny));
}
}
}
static class Coord {
int x;
int y;
public Coord(int x, int y) {
this.x = x;
this.y = y;
}
}
}
'알고리즘' 카테고리의 다른 글
[프로그래머스] 코딩테스트 연습 > 해시 (JavaScript) (0) | 2021.03.11 |
---|---|
[백준] 3055. 탈출 (Java) (0) | 2021.01.24 |
[백준] 17413. 단어 뒤집기2 (Java) (0) | 2021.01.03 |
[백준] 14500. 테트로미노 (Java) (0) | 2020.12.27 |
[백준] 2290. LCDTest (Java) (1) | 2020.12.23 |
- Total
- Today
- Yesterday
- 해시
- 이분탐색
- CustomHook
- 백트래킹
- 백준
- regex
- vue.js
- 삼성역테기출
- BFS
- Validation
- dfs
- BigInteger
- 브루트포스
- form
- REACT
- 우선순위큐
- java
- 문자열
- 정규식
- 프로그래머스
- web
- 그래프
- 구현
- dp
- 알고리즘
- 다익스트라
- matches
- 벨만포드
- 시뮬레이션
- swea
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |