알고리즘/BOJ

[BOJ/python] 2982번 국왕의 방문

frog-in-well 2022. 6. 30. 17:56

2982번 국왕의 방문 파이썬 

출처 - https://www.acmicpc.net/problem/2982

 

2982번: 국왕의 방문

지난주에 상그니 아라비아의 국왕 고둘라 창지즈 영사우드가 한국에 도착했다. 고둘라는 매우 중요한 사람이다. 따라서, 경찰은 그가 타고 있는 차량이 길에 진입했을 때, 그가 길에 있는 동안

www.acmicpc.net

로직은 쉽게 생각할 수 있는 다익스트라 문제였다. 다만 국왕이 도로를 점유하고 있는 상황을 표현하는 방법이 조금 까다로웠다. 메모리를 비효율적으로 사용하더라도 우선 풀어야겠다고 생각했다. 인접 행렬과 인접 리스트를 모두 사용하여 국왕의 위치를 표시했다.

1. 풀이

  • path[u][v]에 u에서 v로 국왕이 이동을 시작한 시간, 도착한 시간을 저장한다. 양방향 그래프이므로 방향과 관계 없이 path[u][v], path[v][u]를 똑같은 값으로 저장한다.
  • 다익스트라에서 출발 지점의 초기 거리값을 K로 갱신하여 국왕이 이동하는 시간과 동기화할 수 있다. 이후 도착 시간에서 K를 빼면 이동 시간을 구할 수 있다.
  • 다익스트라를 수행하며 현재 노드(node), 다음 노드(next) 사이를 국왕이 지나간 시간을 확인한다. path[node][next] = 출발시간, 도착시간
  • 만약 내가 node에 도착한 시간이 출발시간과 도착시간 사이에 있다면 나의 출발 시간을 국왕의 도착시간으로 갱신한다.
  • 다익스트라가 종료되면 B에 도착한 최소 시간에서 출발 시간인 K를 빼고 출력한다.

2. 코드

# boj-2982.py
from heapq import heappop, heappush

N,M = map(int, input().split())
A,B,K,G = map(int, input().split())
king = list(map(int, input().split()))
graph =  [ [] for _ in range(N+1) ]
graph2= [ [0 for _ in range(N+1)] for _ in range(N+1) ]
for _ in range(M):
    u,v,w = map(int, input().split())
    graph[u].append([v,w])
    graph[v].append([u,w])
    graph2[u][v] = w
    graph2[v][u] = w
    
path = [ [ [-1,-1] for _ in range(N+1)] for _ in range(N+1) ]
time = 0
for i in range(1, G):
    before = king[i-1]
    node = king[i]
    path[before][node] = time, time + graph2[before][node]
    path[node][before] = time, time + graph2[before][node]
    time += graph2[before][node]

dist = [float('inf') for _ in range(N+1)]
dist[A]=K
heap = [[K,A]]

while heap:
    cost, node = heappop(heap)
    
    if dist[node] < cost :
        continue
        
    for next, weight in graph[node]:
        
        my_start= cost
        king_start, king_end = path[node][next]
        if king_start<=my_start<=king_end :
            my_start = king_end
        
        if dist[next] > my_start+weight :
            dist[next] = my_start+weight
            heappush(heap, [dist[next], next])

print(dist[B]-K)

2.2 코드(오답)

아래와 같이 인접 리스트만 이용하여 풀었지만 51퍼센트에서 틀렸다. 왜 그런지 아직도 모르겠다.

# boj-2982.py
from heapq import heappop, heappush

N,M = map(int, input().split())
A,B,K,G = map(int, input().split())
king = list(map(int, input().split()))
graph =  [ [] for _ in range(N+1) ]
for _ in range(M):
    u,v,w = map(int, input().split())
    graph[u].append([v,w])
    graph[v].append([u,w])
    
path = [[-1,-1]for _ in range(N+1)]
if G>=1:
    path[king[0]] = [0,0]
    time = 0
    for i in range(1, len(king)):
        node = king[i]
        before = king[i-1]
    
        for next, cost in graph[before]:
            if next== node:
                time += cost
                #어디서 왔는지?, 여기서 다시 출발 시간 언제야? (여기 도착시간)
                path[node] = [before, time]
                break

dist = [float('inf') for _ in range(N+1)]
dist[A]=K
heap = [[K,A]]

while heap:
    cost, node = heappop(heap)
    if dist[node] < cost :
        continue
        
    for next, weight in graph[node]:
        
        my_start,my_end = cost, cost+weight
        #내 출발 지점과 왕 출발지점 같을 때
        if path[next][0] ==node :
            king_start, king_end = path[node][1], path[next][1]
            if king_start<=my_start<king_end :
                my_start = king_end

        #내 출발지점과 왕의 도착 지점이 같을 때
        elif path[node][0] ==next:
            king_start, king_end = path[next][1], path[node][1]
            if king_start<=my_start<king_end:
                my_start = king_end

            
        if dist[next] > my_start+weight :
            dist[next] = my_start+weight
            heappush(heap, [dist[next], next])

print(dist[B]-K)