From 7ba88f8ece87da301bd6c75ff79643718dc627ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=99=95=EC=8A=B9=EC=B2=A0?= Date: Fri, 29 Nov 2024 18:42:35 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20BOJ=2016166=20=EC=84=9C?= =?UTF-8?q?=EC=9A=B8=EC=9D=98=20=EC=A7=80=ED=95=98=EC=B2=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\354\247\200\355\225\230\354\262\240.java" | 124 ++++++++++++++ ...30\354\247\200\355\225\230\354\262\240.md" | 153 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 "ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.java" create mode 100644 "ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.md" diff --git "a/ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.java" "b/ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.java" new file mode 100644 index 00000000..cf143da0 --- /dev/null +++ "b/ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.java" @@ -0,0 +1,124 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; + +public class Main { + static Map> adjMap; + static int N; + static long dest; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + N = Integer.parseInt(br.readLine()); + + adjMap = new HashMap<>(); + + //PQ를 통한 탐색 + //해당 번호(Long)가 갈 수 있는 엣지를 담는 맵을 통해 임의 접근 + for (int i = 0; i < N; i++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int cnt = Integer.parseInt(st.nextToken()); + long pre = Long.parseLong(st.nextToken()); + for (int j = 0; j < cnt - 1; j++) { + long cur = Long.parseLong(st.nextToken()); + Edge edge = new Edge(i, pre, cur); + List edgeList = adjMap.getOrDefault(pre, new ArrayList<>()); + edgeList.add(edge); + adjMap.put(pre, edgeList); + //양방향 + edge = new Edge(i, cur, pre); + edgeList = adjMap.getOrDefault(cur, new ArrayList<>()); + edgeList.add(edge); + adjMap.put(cur, edgeList); + pre = cur; + } + } + dest = Long.parseLong(br.readLine()); + System.out.println(dest == 0 ? 0 : dijkstra()); + } + + private static int dijkstra() { + PriorityQueue pq = new PriorityQueue<>(); + List edgeList = adjMap.getOrDefault(0L, new ArrayList<>()); + for (int i = 0; i < edgeList.size(); i++) { + Edge edge = edgeList.get(i); + Info info = new Info(edge.num, edge.v, 0); + info.set.add(info); + pq.offer(info); + } + int res = -1; + while (!pq.isEmpty()) { + Info info = pq.poll(); + + if (info.v == dest) { + res = info.cnt; + break; + } + + List edges = adjMap.getOrDefault(info.v, new ArrayList<>()); + for (int i = 0; i < edges.size(); i++) { + Edge edge = edges.get(i); + + List nexts = adjMap.getOrDefault(edge.u, new ArrayList<>()); + Info next = new Info(edge.num, edge.u, info.cnt + ((edge.num == info.num) ? 0 : 1)); + if (!info.set.add(next)) continue; + next.set = new HashSet<>(info.set); + pq.offer(next); + for (int j = 0; j < nexts.size(); j++) { + Edge nextEdge = nexts.get(j); + next = new Info(nextEdge.num, nextEdge.v, next.cnt + ((nextEdge.num == next.num) ? 0 : 1)); + Set set = new HashSet<>(info.set); + if (set.add(next)) { + next.set = set; + pq.offer(next); + } + } + } + } + return res; + } +} + +//이동 경로 정보 저장 +class Info implements Comparable { + int num; + long v; + int cnt; + Set set = new HashSet<>(); //isv + + public Info(int num, long v, int cnt) { + this.num = num; + this.v = v; + this.cnt = cnt; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Info info = (Info) o; + return num == info.num && v == info.v; + } + + @Override + public int hashCode() { + return Objects.hash(num, v); + } + + @Override + public int compareTo(Info o) { + return Integer.compare(this.cnt, o.cnt); + } +} + +class Edge { + int num; //호선 + long v, u; //v -> u; + + public Edge(int num, long v, long u) { + this.num = num; + this.v = v; + this.u = u; + } +} \ No newline at end of file diff --git "a/ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.md" "b/ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.md" new file mode 100644 index 00000000..e40e3b7d --- /dev/null +++ "b/ys4512558/Week_45/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240/BOJ_16166_\354\204\234\354\232\270\354\235\230\354\247\200\355\225\230\354\262\240.md" @@ -0,0 +1,153 @@ +# 소스코드 + +```Java +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; + +public class Main { + static Map> adjMap; + static int N; + static long dest; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + N = Integer.parseInt(br.readLine()); + + adjMap = new HashMap<>(); + + //PQ를 통한 탐색 + //해당 번호(Long)가 갈 수 있는 엣지를 담는 맵을 통해 임의 접근 + for (int i = 0; i < N; i++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int cnt = Integer.parseInt(st.nextToken()); + long pre = Long.parseLong(st.nextToken()); + for (int j = 0; j < cnt - 1; j++) { + long cur = Long.parseLong(st.nextToken()); + Edge edge = new Edge(i, pre, cur); + List edgeList = adjMap.getOrDefault(pre, new ArrayList<>()); + edgeList.add(edge); + adjMap.put(pre, edgeList); + //양방향 + edge = new Edge(i, cur, pre); + edgeList = adjMap.getOrDefault(cur, new ArrayList<>()); + edgeList.add(edge); + adjMap.put(cur, edgeList); + pre = cur; + } + } + dest = Long.parseLong(br.readLine()); + System.out.println(dest == 0 ? 0 : dijkstra()); + } + + private static int dijkstra() { + PriorityQueue pq = new PriorityQueue<>(); + List edgeList = adjMap.getOrDefault(0L, new ArrayList<>()); + for (int i = 0; i < edgeList.size(); i++) { + Edge edge = edgeList.get(i); + Info info = new Info(edge.num, edge.v, 0); + info.set.add(info); + pq.offer(info); + } + int res = -1; + while (!pq.isEmpty()) { + Info info = pq.poll(); + + if (info.v == dest) { + res = info.cnt; + break; + } + + List edges = adjMap.getOrDefault(info.v, new ArrayList<>()); + for (int i = 0; i < edges.size(); i++) { + Edge edge = edges.get(i); + + List nexts = adjMap.getOrDefault(edge.u, new ArrayList<>()); + Info next = new Info(edge.num, edge.u, info.cnt + ((edge.num == info.num) ? 0 : 1)); + if (!info.set.add(next)) continue; + next.set = new HashSet<>(info.set); + pq.offer(next); + for (int j = 0; j < nexts.size(); j++) { + Edge nextEdge = nexts.get(j); + next = new Info(nextEdge.num, nextEdge.v, next.cnt + ((nextEdge.num == next.num) ? 0 : 1)); + Set set = new HashSet<>(info.set); + if (set.add(next)) { + next.set = set; + pq.offer(next); + } + } + } + } + return res; + } +} + +//이동 경로 정보 저장 +class Info implements Comparable { + int num; + long v; + int cnt; + Set set = new HashSet<>(); //isv + + public Info(int num, long v, int cnt) { + this.num = num; + this.v = v; + this.cnt = cnt; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Info info = (Info) o; + return num == info.num && v == info.v; + } + + @Override + public int hashCode() { + return Objects.hash(num, v); + } + + @Override + public int compareTo(Info o) { + return Integer.compare(this.cnt, o.cnt); + } +} + +class Edge { + int num; //호선 + long v, u; //v -> u; + + public Edge(int num, long v, long u) { + this.num = num; + this.v = v; + this.u = u; + } +} +``` + +# 소요시간 + +1시간 30분 + +# 알고리즘 + +> 다익스트라, BFS + +# 풀이 + +# BOJ 16166 서울의 지하철 + +1. Map에 역번호, List 형식으로 해당 역에서 갈 수 있는 모든 역 (다른 호선도 가능)을 저장 +2. Edge는 호선, v -> u 의 정보 저장 +3. Info는 호선, 역, 환승 횟수, isv역할의 Set 저장, 다익스트라를 사용하기 위해 환승 횟수를 기준으로 비교 +4. 초기에 인접 역들을 양방향으로 Edge를 만들고 Map에 세팅해준다. +5. 다익스트라 알고리즘을 통해 0번역에서 탐색 시작 +6. HashSet을 통해 방문 여부를 확인하므로 equals, hashCode재정의 (호선, 역) +7. 탐색 시 해당 (호선, 역)에서 갈 수 있는 인접 `역`을 먼저 탐색 후 해당 `역`의 다른 호선을 추가하는 방식으로 탐색 +8. 같은 호선이라면 0 다른 호선이라면 1을 더해주어 환승 카운팅 +9. 탐색 도중 목적지에 도착하면 res를 환승 횟수로 갱신하고 break; +10. 최종적으로 res를 반환하여 출력 (res의 초기값은 -1으로 목적지 도달 불가 시 -1 반환) + +---