[BaekJoon 1446 : 다익스트라, Python] - 지름길

2021, Nov 04    


백준 1446 지름길 : 실버 1



Solution


1. 짧은 풀이


다익스트라 알고리즘으로 분류되었지만, 풀이 방식은 전형적인 다익스트라와 조금 다르다.
어차피 노드 수가 많지 않기 때문에 (< 10,000) 굳이 최소거리 노드를 반환하는 heapq 를 쓰지 않고 for 문을 처음부터 다 도는 풀이이다.
heapq 를 정렬하는 데 드는 O(logn) 만큼의 시간이 안 걸렸고 + for 문을 도는 데 많은 시간이 걸리지 않았기 때문에 실제 코드를 돌리는 데 소요시간은 아래 정석적인 다익스트라를 활용한 풀이와 거의 비슷했다.


import sys
n, total = map(int, input().split())
graph = []
dist = [i for i in range(total+1)]
for _ in range(n):
    s, e, d = map(int, sys.stdin.readline().split())
    graph.append((s, e, d))


for i in dist:
    if i != 0:
        for s, e, d in graph:
            if i == e:     
                dist[i] = min(dist[i], dist[s] + d)
        dist[i] = min(dist[i], dist[i-1]+1)

print(dist[-1])


2. 정석적인 DIKJSTRA

전형적인 다익스트라 풀이 구조를 사용해서 풀었다. 데이터 자체가 크지 않아서 heapq 정렬 과정에서 소요되는 시간이 힙이 최소간선만 반환하는 데서 오는 이득을 상쇄시킨 거 같다.


import sys
from collections import defaultdict
from heapq import *
sys = sys.stdin.readline

n, d = map(int, input().split())
graph = defaultdict(list)          # 0~150, default : 자기 노드 + 1 과 연결되어 있음
for i in range(d):
    graph[i].append([i+1, 1])    # connected node, weight

for _ in range(n):
    s, e, l = map(int, input().split()) 
    if e <= d:
        graph[s].append([e, l])         # 지름길로 연결된 노드도 추가

mindist = [float('inf') for _ in range(d+1)]       
hq = []
heappush(hq, [0, 0])  # 현재 노드까지 오면서 누적된 wgt, node

while hq:
    cur_w, cur_n = heappop(hq)
    if mindist[cur_n] < cur_w: continue     # 더이상 작아질 수 없음
    
    for nxt_n, nxt_w in graph[cur_n]:
        dist = cur_w + nxt_w
        if mindist[nxt_n] > dist:
            mindist[nxt_n] = dist
            heappush(hq, [mindist[nxt_n], nxt_n])       # else : 이미 더 작은 거리로 힙큐에 들어가 있음

print(mindist[d])


풀이과정 및 느낀점


위에서 설명한 것처럼 두 가지 풀이로 전개될 수 있고, 두 풀이 간에 시간차이는 얼마 나지 않는다.
이 문제를 풀 때 주의해야 할 점은,

  • 일방통행이다.
  • 모든 도로상의 위치는 정수로 표현 됨.
  • 그리디가 아님. 지름길이라고 무조건 선택 X (나중에 더 빠른 지름길이 나올 수도 있음)