www.acmicpc.net/problem/14938

 

14938번: 서강그라운드

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

www.acmicpc.net


문제 설명

왼쪽 예제를 오른쪽 그래프로 표현할 수 있습니다.

첫째 줄에는 지역의 개수(n), 수색 범위(m), 길의 개수(r)이 주어집니다.

둘째 줄에는 n개의 숫자가 차례대로 각 구역에 있는 아이템의 수를 나타냅니다.

세 번째 줄부터 r+2번째 줄 까지 지역의 번호 a, b와 길의 길이 i가 주어집니다.

 

이 때, 각 지역에서 수색 범위(m) 내에서 다른 지역으로 이동했을 때 얻을 수 있는 최대 아이템 개수를 구해야 합니다.

 

m이 5로 주어졌을 때 2번 지역에서는 "1번, 3번, 5번"으로 이동할 수 있습니다.

2번->1번->4번은 8(0+3+5)의 수색 범위를 가지므로 이동할 수 없습니다.

 

문제 특성

각 노드에서 다른 노드로 이동했을 때 최소 경로를 구해야 합니다.

따라서 다익스트라 알고리즘을 적용합니다.

 

알고리즘

1. 1 ~ n번 지역에서 다익스트라 알고리즘 수행  : 각 지역에서 다른 지역으로 이동했을 때 최소 경로를 구합니다.

3. 각 지역에서의 최소 경로 중 m 이하인 수색 범위의 구역에 있는 아이템 개수를 구합니다.

4. 이전 지역과 비교하여 더 많은 아이템 개수로 갱신합니다.

 

다익스트라 알고리즘

다익스트라 알고리즘의 전체 과정은 다음과 같습니다. 1번~4번 수행과정을 따라 알고리즘을 파악하시면 됩니다!

참고로 0번 인덱스의 [3, 5]에 대해 과정이 모두 수행된 다음에 [1, 3]에서 0(heap[1])과 더하고 dy와 비교하는 과정이 수행됩니다. 

 

이어서 각 리스트 변수에 대한 세부 사항을 설명하겠습니다.

1. graph는 각 노드 간의 정보를 담고 있습니다.

graph는 총 n 개의 길이를 가지며, 인덱스는 노드 번호를 의미합니다.

 - 문제에서 1번 지역을 graph에서는 0(1-1)번 인덱스로 담았습니다.

또한, graph의 각 인덱스는 복수 개의 [인접한 노드번호, 거리]를 가질 수 있습니다.

 

2. dy는  한 지역에서 다른 지역으로 이동할 때 최소 거리를 담고 있습니다.

 - dy는 총 n 개의 길이를 가지며, 인덱스는 노드 번호를 의미합니다.

 - dy의 인덱스 초기 값은 int의 최대 값으로 설정합니다. 이 값은 지역 간 이동할 수 있는 최소 거리를 의미합니다.

 - 가령, 2번 지역에서 4번 노드로 이동할 때는 8(3+5)이 최소거리입니다.  따라서 알고리즘이 수행된 후에 dy의 1번 인덱스는 8이 리턴되어야 합니다.

 

3. heap는  다른 지역으로 이동할 때, 중간 경로의 역할을 수행합니다.

- heap에 들어가는 초기 값은 (출발 지역 번호, 0)입니다. 뒤에 있는 0은 이동해야 하는 거리를 의미합니다.

  - 가령 3번 지역에서 출발한다면  (2, 0) 입니다. (출발 지역 번호-1이므로) 

  - 0번에서 0번을 이동하므로, 초기 거리는 0입니다.

- heap 리스트가 비었을 때 다익스트라 알고리즘은 종료됩니다.

 

코드

import sys
import heapq
sys.stdin = open("C:/Users/JIn/PycharmProjects/coding_Test/input.txt", "rt")


def dijstra(x):
    dy = [sys.maxsize] * n
    dy[x] = 0
    heap = [[x, dy[x]]]
    while heap:
        node, dis = heapq.heappop(heap)
        for i in range(len(graph[node])):
            next = graph[node][i]
            if dy[next[0]] > dis + next[1]:
                dy[next[0]] = dis + next[1]
                heapq.heappush(heap, [next[0], dis + next[1]])
    return dy

if __name__ == "__main__":
    n, m, r = map(int, input().split())  # 지역의 개수, 수색범위, 길의 개수
    numItem = list(map(int, input().split()))  # 인덱스는 지역 번호를 의미
    graph = [[] for _ in range(n)]
    for _ in range(r):
        a, b, i = map(int, input().split())  # 연결된 지역의 번호(a, b), 길의 길이(i)
        graph[a - 1].append([b - 1, i])
        graph[b - 1].append([a - 1, i])
    res = 0
    for i in range(n):    # 각 노드에서 최소 경로탐색
        minPath = dijstra(i)
        add = 0
        for j in range(n):    # 최소 경로가 m 이하일 때 획득할 수 있는 아이템 수
            if minPath[j] <= m:
                add += numItem[j]
        res = max(res, add)
print(res)

'코딩 테스트' 카테고리의 다른 글

[백준 13458] 시험 감독  (0) 2021.02.24
[프로그래머스] 위장  (0) 2021.02.22
[백준 10775] 공항 - 유니온파인드(union-find) 문제  (0) 2021.02.16
[백준] 9009 피보나치  (0) 2021.02.10
[백준] 11967 불켜기  (0) 2021.02.10

+ Recent posts