Greedy 기출문제 풀이

다익스트라 알고리즘

  • 설명 : 아래의 가중치 방향그래프에서 1번 정점에서 모든 정점으로의 최소 거리비용을 출력하는 프로 그램을 작성하세요. (경로가 없으면 Impossible를 출력한다)
  • image

  • 입력 : 첫째 줄에는 정점의 수 N(1<=N<=20)와 간선의 수 M가 주어진다. 그 다음부터 M줄에 걸쳐 연 결정보와 거리비용이 주어진다.

  • 출력 : 1번 정점에서 각 정점으로 가는 최소비용을 2번 정점부터 차례대로 출력하세요

  • 풀이

package org.example;

import java.util.*;

class Point implements Comparable<Point> {
    int point;
    int value;

    public Point(int point, int value) {
        this.point = point;
        this.value = value;
    }

    @Override
    public int compareTo(Point p) {
        return this.point-p.point;
    }
}

public class Main {

    static List<List<Point>> list = new ArrayList<>();

    static int[] dis;

    public void solution(int idx) {
        PriorityQueue<Point> pQ = new PriorityQueue<>();
        pQ.offer(new Point(idx, 0));
        dis[idx]=0;
        while(!pQ.isEmpty()){
            Point tmp = pQ.poll();
            int tmp_p = tmp.point;
            int tmp_v = tmp.value;
            if(dis[tmp_p]<tmp_v) continue;
            for (Point edge : list.get(tmp_p)) {
                if(dis[edge.point]>edge.value+tmp_v){
                    dis[edge.point] = edge.value+tmp_v;
                    pQ.offer(new Point(edge.point, edge.value+tmp_v));
                }
            }
        }
    }

    public static void main(String[] args) {
        
        Main main = new Main();
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        dis = new int[n+1];
        Arrays.fill(dis, Integer.MAX_VALUE);
        for(int i=0; i<=n; i++){
            list.add(new ArrayList<Point>());
        }
        int m = scan.nextInt();
        for(int i=0; i<m; i++){
            int a = scan.nextInt();
            int b = scan.nextInt();
            int c = scan.nextInt();
            list.get(a).add(new Point(b, c));
        }
        main.solution(1);

        for(int i=2; i<=n; i++){
            if(dis[i]==Integer.MAX_VALUE) System.out.println(i+" : possible");
            else System.out.println(i+" : "+dis[i]);
        }

    }
}


  • 정리
    • 우선 입력값을 각 이동 정점과 값을 담은 Point객체로 만들어 주고, 이를 기존 정점의 리스트로 담은 2중 리스트를 만들 것임
    • 그리고 각 정점마다 이동 값을 담을 dis배열을 static으로 만들어 줌
    • 기준이 되는 1을 매개변수로 하여 메서드에 진입
    • 우선순위 큐에 현재 정점과 데이터 (1에서 1로 이동하는 값은 당연히 0)를 넣고, dis에도 0값을 담아줌
    • 우선순위큐가 비지 않았을경우(=이동할 정점이 있을 경우)
    • 그중 제일 적은 값을 꺼낸 다음(=우선순위 큐기때문에 poll만 해주면 됨) 현재 정점과 이동값을 변수에 담아주고
    • 거기서 이동해야 하는 정점들을 반복을 돌림
    • 현재값+이동정점값을 더한것이 기존의 dis[이동정점]의 값보다 작을 경우에만 교체, 새로운 정점의 이동경로를 재탐색함
    • 이 과정이 모두 끝났음에도 dis값이 변동없이 계속 int 최대값이라면 이동되지 않는 변수로 감안하고 impossible을 출력함

Updated: