Algorithm/백준

[Java] BaekJoon 14938. 서강그라운드 (골드4) (Dijkstra)

Per ardua ad astra ! 2021. 10. 3. 12:48

문제출처: https://www.acmicpc.net/problem/14938

 

14938번: 서강그라운드

예은이는 요즘 가장 인기가 있는 게임 서강그라운드를 즐기고 있다. 서강그라운드는 여러 지역중 하나의 지역에 낙하산을 타고 낙하하여, 그 지역에 떨어져 있는 아이템들을 이용해 서바이벌을

www.acmicpc.net

 

문제이해

 

목표

그래프 -> 노드 : 지역, 간선 : 길
각 노드에는 얻을 수 있는 아이템 개수가 할당되어 있다. 
예은이의 수색범위(M)이 주어질 때, M이하의 비용으로 갈 수 있는 지역은 다 방문이 가능하다. 
예은이가 얻을 수 있는 최대 아이템 개수를 출력하자.

 

풀이

 

다익스트라를 이용한 기본문제이다. 

모든 노드가 첫 번째 노드가 되어 n번의 다익스트라를 진행한다. 

 

단, 가지치기를 하면서 진행 할 때, 비용이 M이하인 경우에만 진행할 수 있도록하자. 

M 초과인 비용이라면 더이상 탐색을 진행하지 않는다. 

 

한 번의 Dijkstra가 끝이나면, 방문했던 적이 있는 노드의 아이템 개수를 모두 합하여
최대 아이템 개수(answer)와 비교해서 갱신 시켜준다.

 

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;

import static java.lang.System.in;

public class 서강그라운드 {
    static class Edge {
        int dest;
        int price;

        public Edge(int dest, int price) {
            this.price = price;
            this.dest = dest;
        }

    }

    static final int MAX = 1000000;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String[] strArr;
        strArr = br.readLine().split(" ");
        int N = Integer.parseInt(strArr[0]); // 노드 개수
        int M = Integer.parseInt(strArr[1]); // 수색범위
        int E = Integer.parseInt(strArr[2]); // 길의ㅏ개수
        int[] items = new int[N];
        // 아이템
        strArr = br.readLine().split(" ");
        ArrayList<Edge>[] arrayList = new ArrayList[N]; // 인접리스트
        for (int i = 0; i < N; i++) { // 아이탬수
            items[i] = Integer.parseInt(strArr[i]);
            arrayList[i] = new ArrayList<>();
        }

        for (int i = 0; i < E; i++) { // 간선 정보
            strArr = br.readLine().split(" ");
            int start = Integer.parseInt(strArr[0]) - 1;
            int dest = Integer.parseInt(strArr[1]) - 1;
            int price = Integer.parseInt(strArr[2]);
            arrayList[start].add(new Edge(dest, price));
            arrayList[dest].add(new Edge(start, price));
        }


        // 다익스트라 시작
        int[] minDp = new int[N];
        int answer = 0;
        PriorityQueue<Edge> queue = new PriorityQueue<Edge>(Comparator.comparingInt(a -> a.price));
        for (int start = 0; start < N; start++) { // (0 -> 시작노드 (price = 0))
            Arrays.fill(minDp, MAX);
            minDp[start] = 0;
            queue.add(new Edge(start, 0));
            while (!queue.isEmpty()) {
                Edge edge = queue.poll();
                if (minDp[edge.dest] < edge.price) { // 갱신필요 x
                    continue;
                }
                for (Edge nextEdge : arrayList[edge.dest]) {
                    int nextPrice = edge.price + nextEdge.price;
                    if (nextPrice <= M && minDp[nextEdge.dest] > nextPrice) {
                        minDp[nextEdge.dest] = nextPrice;
                        queue.add(new Edge(nextEdge.dest, nextPrice));
                    }
                }
            }
            int sum = 0;
            for (int j = 0; j < N; j++) {
                if (minDp[j] != MAX) {
                    sum += items[j];
                }
            }
            answer = Math.max(answer, sum);
        }

        System.out.println(answer);
    }
}