💡Problem Solving/BOJ

[BOJ 10217] KCM Travel (Java)

gom20 2021. 12. 9. 18:04

문제

https://www.acmicpc.net/problem/10217

 

10217번: KCM Travel

각고의 노력 끝에 찬민이는 2014 Google Code Jam World Finals에 진출하게 되었다. 구글에서 온 초대장을 받고 기뻐했던 것도 잠시, 찬찬히 읽어보던 찬민이는 중요한 사실을 알아차렸다. 최근의 대세

www.acmicpc.net

 

풀이

다익스트라 알고리즘을 사용하여 풀 수 있다. 

보통 최소 거리(시간)을 저장할 배열로 1차 배열을 사용하지만 

여기서는 비용을 고려해야 하므로 2차 배열로 생성 하여 사용한다. 

 

소스코드

package dijkstra;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;

public class BOJ10217 {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int T = Integer.parseInt(br.readLine());
        for(int i = 0; i < T; i++){
            bw.write(solution(br) + "\n");
        }
        bw.flush();
    }

    public static class Edge{
        int to;
        int cost;
        int time;
        public Edge(int to, int cost, int time){
            this.to = to;
            this.cost = cost;
            this.time = time;
        }
    }

    public static class Info{
        int node;
        int accuCost;
        int accuTime;
        public Info(int node, int accuCost, int accuTime){
            this.node = node;
            this.accuCost = accuCost;
            this.accuTime = accuTime;
        }
    }

    public static String solution(BufferedReader br) throws Exception {
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken()); // 노드의 개수
        int M = Integer.parseInt(st.nextToken()); // 최대 비용
        int K = Integer.parseInt(st.nextToken()); // 간선 개수

        // 인접 노드 리스트 생성
        ArrayList<Edge>[] adjs = new ArrayList[N+1];
        for(int i = 0; i <= N; i++){
            adjs[i] = new ArrayList<Edge>();
        }

        // 인접 노드 정보 Input 처리
        for(int i = 0; i < K; i++){
            st = new StringTokenizer(br.readLine());
            int from = Integer.parseInt(st.nextToken());
            int to = Integer.parseInt(st.nextToken());
            int cost = Integer.parseInt(st.nextToken());
            int time = Integer.parseInt(st.nextToken());
            adjs[from].add(new Edge(to, cost, time));
        }

        //dp[i][j] = 시작점에서 i까지 비용 j로 가는데 걸리는 최소 시간
        int[][] dp = new int[N+1][M+1];
        for(int i = 0; i <= N; i++){
            Arrays.fill(dp[i], Integer.MAX_VALUE);
        }

        // 시간 오름차순 정렬
        PriorityQueue<Info> pq = new PriorityQueue<Info>(new Comparator<Info>(){
            @Override
            public int compare(Info i1, Info i2){
                return i1.accuTime - i2.accuTime;
            }
        });

        // 시작 Node(1번)에서 1번 Node까지 0의 비용으로 0시간걸림
        dp[1][0] = 0;
        pq.offer(new Info(1, 0, 0));

        while(!pq.isEmpty()){
            Info cur = pq.poll();

            // 시작 노드에서 cur.node 까지 cur.accCost 비용으로 간 dp에 저장된 최소 시간보다
            // 현재 누적해서 온 시간이 클 경우 갱신을 하지 않는다.
            if(dp[cur.node][cur.accuCost] < cur.accuTime) continue;

            for(Edge adj : adjs[cur.node]){
                int accuTime = cur.accuTime + adj.time;
                int accuCost = cur.accuCost + adj.cost;

                // 누적해온 비용이 M보다 커졌다면 갱신하지 않는다.
                if(accuCost > M) continue;

                // 시작 노드에서 adj.to까지 accuCost 비용으로 간 dp 저장된 최소 시간이
                // 현재까지 계산된 누적 최소 시간보다 같거나 작다면 갱신하지 않는다.
                if(dp[adj.to][accuCost] <= accuTime) continue;

                // 시작 노드에서 adj.to까지 accuCost비용을 내고 dp[adj.to][accuCost] 최소 시간이 걸렸다.
                // 그렇다면 adj.to까지 accuCost 이상의 비용을 냈는데 dp[adj.to][accuCost] 최소 시간보다 오래 걸렸다면
                // 최소 시간을 갱신해준다.
                for(int i = accuCost; i <= M; i++){
                    if(dp[adj.to][i] > accuTime){
                        dp[adj.to][i] = accuTime;
                    }
                }
                dp[adj.to][accuCost] = accuTime;
                pq.offer(new Info(adj.to, accuCost, accuTime));

            }
        }

        int min = Integer.MAX_VALUE;
        for(int j = 0; j <= M; j++){
            min = Math.min(min, dp[N][j]);
        }
        return (min == Integer.MAX_VALUE)? "Poor KCM" : String.valueOf(min);
    }
}

 

'💡Problem Solving > BOJ' 카테고리의 다른 글

[BOJ 2529] 부등호 (Java)  (0) 2021.12.11
[BOJ 15686] 치킨 배달 (Java, Python)  (0) 2021.12.10
[BOJ 14716] 현수막 (Java)  (0) 2021.12.09
[BOJ 2170] 선 긋기 (Java)  (0) 2021.12.08
[BOJ 5419] 북서풍 (Java)  (0) 2021.12.07