🙇♂️ URL : https://www.acmicpc.net/problem/16928
🤷♂️ Difficulty: ?
💆♂️ Submissions : Success
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class App {
static int M, N;
static int[] next = new int[101]; // 다음 이동 장소
static int[] dist = new int[101]; // 최소 이동 거리
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
// 첫째 줄에 게임판에 있는 사다리의 수 N(1 ≤ N ≤ 15)과 뱀의 수 M(1 ≤ M ≤ 15)이 주어진다.
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
for(int i=0; i<next.length; i++) {
next[i] = i;
dist[i] = -1;
}
// 둘째 줄부터 N개의 줄에는 사다리의 정보를 의미하는 x, y (x < y)가 주어진다.
// x번 칸에 도착하면, y번 칸으로 이동한다는 의미이다.
for(int i=0; i<N; i++) {
String[] ladders = br.readLine().split(" ");
next[Integer.parseInt(ladders[0])] = Integer.parseInt(ladders[1]);
}
// 다음 M개의 줄에는 뱀의 정보를 의미하는 u, v (u > v)가 주어진다.
// u번 칸에 도착하면, v번 칸으로 이동한다는 의미이다.
for(int i=0; i<M; i++) {
String[] snakes = br.readLine().split(" ");
next[Integer.parseInt(snakes[0])] = Integer.parseInt(snakes[1]);
}
// 게임의 목표는 1번 칸에서 시작해서 100번 칸에 도착하는 것이다.
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
dist[1] = 0;
// 100번 칸에 도착하기 위해 주사위를 굴려야 하는 횟수의 최솟값을 구해보자.
System.out.println(solution(queue));
}
public static int solution(Queue<Integer> queue) {
while(!queue.isEmpty()) {
int location = queue.poll();
for(int i=1; i<=6; i++) {
int nextLocation = location + i;
// 만약 주사위를 굴린 결과가 100번 칸을 넘어간다면 이동할 수 없다.
if(nextLocation <= 100) {
// 사다리 혹은 뱀이 존재한다면, 해당 위치로 이동
// 만약 없다면 자기 자신이 그대로 값이 될 것이다.
nextLocation = next[nextLocation];
// 아직 방문하지 않은 경우 -> 이동횟수 + 1
// BFS -> 가장 먼저 해당 칸을 방문했다 = 가장 적은 횟수로 해당 칸으로 이동했다는 의미
if(dist[nextLocation] < 0) {
dist[nextLocation] = dist[location] + 1;
queue.offer(nextLocation);
}
}
}
}
// 100번째 칸의 이동 횟수를 출력
return dist[100];
}
}
본 문제의 핵심은 '100번 칸에 도착하기 위해 주사위를 굴려야 하는 횟수의 최솟값'을 구하는 것이다.
이 문제에서는 두 개의 배열을 만들었다.
- 뱀 또는 사다리의 정보가 적혀있는 배열. 다르게 말하면 "현재에 머물러야 할지, 혹은 한번 더 다른 칸으로 이동해야 하는지 적혀있는" 배열
- 현재 위치까지 이동한 가장 적은 횟수를 담고 있는 배열
static int[] next = new int[101]; // 다음 이동 장소
static int[] dist = new int[101]; // 최소 이동 거리
...
for(int i=0; i<101; i++) {
next[i] = i;
dist[i] = -1;
}
...
// 둘째 줄부터 N개의 줄에는 사다리의 정보를 의미하는 x, y (x < y)가 주어진다.
// x번 칸에 도착하면, y번 칸으로 이동한다는 의미이다.
for(int i=0; i<N; i++) {
String[] ladders = br.readLine().split(" ");
next[Integer.parseInt(ladders[0])] = Integer.parseInt(ladders[1]);
}
// 다음 M개의 줄에는 뱀의 정보를 의미하는 u, v (u > v)가 주어진다.
// u번 칸에 도착하면, v번 칸으로 이동한다는 의미이다.
for(int i=0; i<M; i++) {
String[] snakes = br.readLine().split(" ");
next[Integer.parseInt(snakes[0])] = Integer.parseInt(snakes[1]);
}
예제 입력 1의 예시에 따르면, next 배열은 아래와 같은 구조를 가질 것이다.
- next[32] = 62
- next[42] = 68
...
- next[95] = 13
...
- next[75] = 19
...
최소 거리를 구한다는 것은 무조건 BFS를 사용하라는 의미로 보면 된다.
처음 시작 값인 1을 큐에 넣어두고, 주사위(1부터 6)를 굴려가며 100까지 이동하는 최단 거리를 찾으면 된다. 단, "100번 칸을 넘어간다면 이동할 수 없다"는 조건이 있기 때문에, 주사위를 굴려 이동한 칸이 100을 넘어가서는 안된다.
...
while(!queue.isEmpty()) {
int location = queue.poll();
for(int i=1; i<=6; i++) {
int nextLocation = location + i;
// 만약 주사위를 굴린 결과가 100번 칸을 넘어간다면 이동할 수 없다.
if(nextLocation <= 100) {
// 사다리 혹은 뱀이 존재한다면, 해당 위치로 이동
// 만약 없다면 자기 자신이 그대로 값이 될 것이다.
nextLocation = next[nextLocation];
// 아직 방문하지 않은 경우 -> 이동횟수 + 1
// BFS -> 가장 먼저 해당 칸을 방문했다 = 가장 적은 횟수로 해당 칸으로 이동했다는 의미
if(dist[nextLocation] < 0) {
dist[nextLocation] = dist[location] + 1;
queue.offer(nextLocation);
}
}
}
}
return dist[100];