Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[241129] BOJ 16166 서울의 지하철 #1029

Merged
merged 1 commit into from
Dec 2, 2024

Conversation

ys4512558
Copy link
Collaborator

이슈넘버

#1022

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static Map<Long, List<Edge>> 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<Edge> 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<Info> pq = new PriorityQueue<>();
        List<Edge> 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<Edge> edges = adjMap.getOrDefault(info.v, new ArrayList<>());
            for (int i = 0; i < edges.size(); i++) {
                Edge edge = edges.get(i);

                List<Edge> 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<Info> set = new HashSet<>(info.set);
                    if (set.add(next)) {
                        next.set = set;
                        pq.offer(next);
                    }
                }
            }
        }
        return res;
    }
}

//이동 경로 정보 저장
class Info implements Comparable<Info> {
    int num;
    long v;
    int cnt;
    Set<Info> 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 반환)

@ys4512558 ys4512558 added this to the 45주차 milestone Nov 29, 2024
@ys4512558 ys4512558 self-assigned this Nov 29, 2024
@u1qns u1qns self-requested a review November 29, 2024 14:33
for (int j = 0; j < cnt - 1; j++) {
long cur = Long.parseLong(st.nextToken());
Edge edge = new Edge(i, pre, cur);
List<Edge> edgeList = adjMap.getOrDefault(pre, new ArrayList<>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 이렇게 getOrDefault로 new 할당하는 방식은 새롭네요

Copy link
Member

@u1qns u1qns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 처음에 구현하려고 했던 아이디어랑 유사해서 신기합니다. 끝까지 해낸 당신 최고!

@ys4512558 ys4512558 merged commit 017bf33 into BE-Archive:main Dec 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants