태그: Java
https://www.acmicpc.net/problem/23030
키워드
- 지하철은
양방향 모두 통행이 가능
하며, - 지하철의
방향을 바꿔타는 시간
과지하철을 타기 위해 대기하는 시간
은걸리지 않는다.
- 환승을 하는 경우 걸어서 이동해야 하므로 사용자는 각자
자신이 환승을 하는 데 걸리는 시간 T
- 사용자가 환승 시간 T와 출발지, 도착지를 입력하면
최단 경로로 이동
하였을 때걸리는 소요 시간
을 알려주는 프로그램
구현
가장 어려웠던 것은 ‘이런 지하철을 어떤식으로 저장해야 깔끔하게 저장할 수 있을까’ 였다.
클래스를 선언하여, 현재 노선(Pair.line)과, 현재 역번호(Pair.station)를 저장하였다.
다익스트라 알고리즘을 통해 최단경로를 저장하기 위하여, 노선정보, 역정보, 비용정보를 저장해야 하기에 Pair클래스에 cost필드를 하나 더 추가했다.
단순 역 정보를 저장하는 transferInformation에서는 cost필드를 사용하지 않는다. (나중되면 클래스를 분리하는 것이 더 깔끔할 것 같다.)
transferInformtaion에는 환승 노선과 환승 역번호가 주어진다.
예를들어 1번노선 1번역이 4번노선 2번역과 이어져있다면, transferInformation.get(1).get(1) 의 line은 4고 station은 2이다. (이 부분도 Pair 인스턴스를 갖도록 하면 더욱 깔끔하게 될 것 같다.)
이를 통해여 이동하는 방식이 3가지로 주어진다.
- +1역으로 이동하는 경우
- -1역으로 이동하는 경우
- 환승하는 경우
각각의 경우의 최솟값을 ArrayList<ArrayList> dist 에 저장한다.
시작 노선, 시작역으로부터 dist.get(1).get(2) 은 1번노선 2번역까지 최단시간을 저장한다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.StringTokenizer;
public class java_23030 {
// N개의 노선
static int N;
// M개의 환승역
static int M;
// K개의 사용자 요청 갯수
static int K;
static ArrayList<ArrayList<Pair>> transferInformation;
static class Pair {
// 환승 노선 : 없다면 -1
int line;
// 환승역 : 없다면 -1
int station;
int cost;
public Pair(int line, int station, int cost) {
this.line = line;
this.station = station;
this.cost = cost;
}
public Pair(int line, int station) {
this.line = line;
this.station = station;
}
}
// 시작노선, 시작역, 환승비용이 주어지면 결과값을 반환
static int findRoute(int startLine, int startStation, int endLine, int endStation, int transferCost) {
// 경로 저장
ArrayList<ArrayList<Integer>> dist = new ArrayList<>();
for (int i = 0; i < transferInformation.size(); i++) {
dist.add(new ArrayList<>());
for (int j = 0; j < transferInformation.get(i).size(); j++) {
dist.get(i).add(Integer.MAX_VALUE);
}
}
// 최초 위치 0 처리
dist.get(startLine).set(startStation, 0);
Deque<Pair> deque = new ArrayDeque<>();
deque.add(new Pair(startLine, startStation, 0));
while (!deque.isEmpty()) {
Pair now = deque.poll();
// 원하는 위치에 도착한 경우
if (now.line == endLine && now.station == endStation) {
continue;
}
else {
// +1로 가는 경우
// +1로 갈 수 있는 지 확인
// +1로 가는게 비용이 더 저렴한지 확인
if (now.station + 1 < transferInformation.get(now.line).size()) {
if (now.cost + 1 < dist.get(now.line).get(now.station + 1)) {
dist.get(now.line).set(now.station + 1, now.cost + 1);
deque.add(new Pair(now.line, now.station + 1, now.cost + 1));
}
}
// -1로 가는 경우
// -1로 갈 수 있는 지 확인
// -1로 가는게 비용이 더 저렴한지 확인
if (0 <= now.station - 1) {
if (now.cost + 1 < dist.get(now.line).get(now.station - 1)) {
dist.get(now.line).set(now.station - 1, now.cost + 1);
deque.add(new Pair(now.line, now.station - 1, now.cost + 1));
}
}
// 환승하는 경우
if (transferInformation.get(now.line).get(now.station).line != -1) {
//
int transferLine = transferInformation.get(now.line).get(now.station).line;
int transferStation = transferInformation.get(now.line).get(now.station).station;
if (now.cost + transferCost < dist.get(transferLine).get(transferStation)) {
dist.get(transferLine).set(transferStation, now.cost + transferCost);
deque.add(new Pair(transferLine, transferStation, now.cost + transferCost));
}
}
}
}
return dist.get(endLine).get(endStation);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 출발지, 도착지를 입력하면 최단경로로 이동했을 때 소요시간을 알려줌
// N개의 노선
N = Integer.parseInt(br.readLine());
transferInformation = new ArrayList<>();
for (int i = 0; i < N; i++) {
transferInformation.add(new ArrayList<>());
}
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
// 역의 갯수
int countStation = Integer.parseInt(st.nextToken());
for (int j = 0; j < countStation; j++) {
transferInformation.get(i).add(new Pair(-1, -1));
}
}
// 인접한 역은 1의 시간이 걸림
// M개의 환승역 존재
M = Integer.parseInt(br.readLine());
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int U1 = Integer.parseInt(st.nextToken()) - 1;
int U2 = Integer.parseInt(st.nextToken()) - 1;
int V1 = Integer.parseInt(st.nextToken()) - 1;
int V2 = Integer.parseInt(st.nextToken()) - 1;
transferInformation.get(U1).get(U2).line = V1;
transferInformation.get(U1).get(U2).station = V2;
transferInformation.get(V1).get(V2).line = U1;
transferInformation.get(V1).get(V2).station = U2;
}
// K개의 요청
K = Integer.parseInt(br.readLine());
for (int i = 0; i < K; i++) {
st = new StringTokenizer(br.readLine());
// 환승하는데 걸리는 시간 T
int T = Integer.parseInt(st.nextToken());
int U1 = Integer.parseInt(st.nextToken()) - 1;
int U2 = Integer.parseInt(st.nextToken()) - 1;
int V1 = Integer.parseInt(st.nextToken()) - 1;
int V2 = Integer.parseInt(st.nextToken()) - 1;
int result = findRoute(U1, U2, V1, V2, T);
System.out.println(result);
}
// 다익스트라 사용
br.close();
}
}
'Coding Test > BOJ' 카테고리의 다른 글
[BOJ/JAVA] 2457번: 공주님의 정원 (0) | 2022.10.19 |
---|---|
[BOJ/JAVA] 1543번: 문서 검색 (0) | 2022.10.19 |
[BOJ/JAVA] 1719번: 택배 (1) | 2022.10.03 |
[BOJ/JAVA] 13549번: 숨바꼭질 3 (1) | 2022.10.03 |
[BOJ/JAVA] 2458번: 키 순서 (1) | 2022.09.26 |