거누의 개발노트

[파이썬] 미래 도시 - 이코테 본문

코딩테스트

[파이썬] 미래 도시 - 이코테

Gogozzi 2022. 5. 31. 13:15
반응형

문제

방문 판매원 A는 많은 회사가 모여 있는 공중 미래 도시에 있다.
공중 미래 도시에는 1번부터 N번까지의 회사가 있는데 특정 회사끼리는 서로 도로를 통해 연결되어 있다.
방문 판매원 A 현재 1번 회사에 위치해 (출발 지점) 있으며, X번 회사에 방문해 물건을 판매하고자 한다.

공중 미래 도시에서 특정 회사에 도착하기 위한 방법은 회사끼리 연결되어 있는 도로를 이용하는 방법이 유일하다.
또한 연결된 2개의 회사는 양방향으로 이동할 수 있다.
공중 미래 도시에서의 도로는 마하의 속도로 사람을 이동시켜주기 때문에 특정 회사와 다른 회사가 도로로 연결되어 있다면, 확히 1만큼의 시간으로 이동할 수 있다. ( 모든 간선은 1의 비용 )

또한 오늘 방문 판매원 A는 기대하던 소개팅에도 참석하고자 한다. 소개팅의 상대는 K번 회사에 존재한다.
방문 판매원 A X번 회사에 가서 물건을 판매하기 전에 먼저 소개팅 상대의 회사에 찾아가서 함께 커피를 마실 예정이다. 따라서 방문 판매원 A 1번 회사에서 출발하여 K번 회사를 방문한 뒤에 X번 회사로 가는 것이 목표다.
이때 방문 판매원 A는 가능한 한 빠르게 이동하고자 한다.
방문 판매원이 회사 사이를 이동하게 되는 최소 시간을 계산하는 프로그램을 작성하시오.

를 들어 N = 5, X = 4, K = 5이고 회사 간 도로가 7개면서 각 도로가 다음과 같이 연결되어 있을 때를 가정할 수 있다.

결론, A라는 판매원이 1번회사에서 출발하여 K라는 회사를 들린 후에 X에 있는 회사를 방문할 때의, 최단 경로로 가는 거리를 구하면 되는 문제 ( 모든 도로를 지나가는 비용은 1 이다. )

오늘 배운 다익스트라 알고리즘을 적용해보자.

예제 입력

5 7 <- 회사의 개수(노드), 연결된 도로의 개수(간선)
1 2
1 3
1 4
2 4
3 4
3 5
4 5
4 5 <- 최종도착 회사, 들려다갈 곳

출력 예시

3

작성한 전체 코드

import heapq
import sys
INF = int(1e9)

# 플로이드 워셜 알고리즘 : O(N^3)
# for으로 갈 수 있는 최소값을 구하는 다익스트라 알고리즘 O(N^2)
# 우선순위 큐를 이용한 다익스트라 알고리즘: O(NlogN)
def dijkstra_pq(graph, start):
    # 최소 거리의 값들을 담을 리스트 선언
    dist = [INF] * len(graph)

    q = []
    # 가장 가깝고 방문안한 노드를 구하기 위해서
    # heapq 내장 함수이용 ( 최소 힙 )
    # 먼저, 출발 값을 넣는다.
    heapq.heappush(q, (0, start))
    # 첫번째 노드에서 첫번째 노드로 가는 거리는 0
    dist[start] = 0

    # 힙이 존재하는 동안 반복 한다.
    while q:

        acc, cur = heapq.heappop(q)

        # 거리 리스트에 값이 힙에서 꺼낸 값보다 작으면
        # 이미 최단거리이기 때문에 업데이트 할 필요가 없음
        # 1번케이스 무한대 < 0 = False
        if dist[cur] < acc:
            continue


        # 인접 노드를 차례대로 살펴보며 거리를 업데이트한다.
        # cur이 1번 노드라고 생각한다면
        for adj, d in graph[cur]:
            # 1번 노드와 연결된 노드들의 거리를 계산한후
            # 최단거리 리스트에 있는 값과 비교해서 계산한 값이 작으면
            # 업데이트 해주고, 2, 3, 4에 연결된 노드들을 확인 하는 방식으로 반복된다.
            cost = acc + d
            if cost < dist[adj]:
                dist[adj] = cost
                heapq.heappush(q, (cost, adj))

    return dist


input = sys.stdin.readline
# n: 회사의 개수(노드), m : 도로의 개수(간선)
n, m = map(int, input().split())
# 계산을 편하게 하기위해 n+1의 이중 배열을 만든다.
graph = [[] for _ in range(n + 1)]

# 간선들을 그래프로 만들건데
for _ in range(m):
    a, b = map(int, input().split())
    #a를 기준으로 b와 연결된 그래프를 만들거고, a와 b 사이 거리
    #양방향 이동가능하기 때문에
    graph[a].append((b, 1))
    graph[b].append((a, 1))

# 도착할 회사 X, 경유할 회사 K
X, K = map(int, input().split())

# print(graph)
[[], [(2, 1), (3, 1), (4, 1)], [(1, 1), (4, 1)], [(1, 1), (4, 1), (5, 1)], [(1, 1), (2, 1), (3, 1), (5, 1)], [(3, 1), (4, 1)]]


# 1에서 K 까지의 최단거리, K=5
rtn1 = dijkstra_pq(graph, 1)
distanceK = rtn1[K]
# [1000000000, 0, 1, 1, 1, 2]

# K에서 X 까지의 최단거리, X=4
rtn2 = dijkstra_pq(graph, K)
distanceX = rtn2[X]
# [1000000000, 2, 2, 1, 1, 0]

# 1~K까지의 최단거리 + K~X까지의 최단거리
distance = distanceK+distanceX
if distance >= INF:
    print(-1)
else:
    print(distance)

 

반응형
Comments