프로그래머스 - 섬 연결하기 (Greedy)Python

timo·2021년 1월 8일
0
post-thumbnail

문제 설명

n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.

다리를 여러 번 건너더라도, 도달할 수만 있으면 통행 가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.

제한사항

  • 섬의 개수 n은 1 이상 100 이하입니다.
  • costs의 길이는 ((n-1) * n) / 2이하입니다.
  • 임의의 i에 대해, costs[i][0] 와 costs[i][1]에는 다리가 연결되는 두 섬의 번호가 들어있고, costs[i][2]에는 이 두 섬을 연결하는 다리를 건설할 때 드는 비용입니다.
  • 같은 연결은 두 번 주어지지 않습니다. 또한 순서가 바뀌더라도 같은 연결로 봅니다. 즉 0과 1 사이를 연결하는 비용이 주어졌을 때, 1과 0의 비용이 주어지지 않습니다.
  • 모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.
  • 연결할 수 없는 섬은 주어지지 않습니다.

입출력 예

ncostsreturn
4[[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]]4

입출력 예 설명

costs를 그림으로 표현하면 다음과 같으며, 이때 초록색 경로로 연결하는 것이 가장 적은 비용으로 모두를 통행할 수 있도록 만드는 방법입니다.


최소신장트리를 구하는 문제이다. 나는 프림 알고리즘을 사용했다.

def solution(n, costs):
    d = [float('inf') for i in range(n)]
    d[0] = 0
    Q = {i for i in range(n)} #Q는 아직 연결되지 않은 노드들의 집합
    answer = 0
    while len(Q) != 0:
        u = deleteMin(Q, d)
        answer += d[u]
        #정점 u와 인접한 정점을 찾는다
        for line in costs:
            for idx in range(2):
                if line[idx] == u: #정점 u와 연결되어있음]
                    if line[1-idx] in Q and line[2] < d[line[1-idx]]:
                        d[line[1-idx]] = line[2]
    return answer

def deleteMin(Q, d):
    minWeight = float('inf')
    minNode = None
    for node in Q:
        if d[node] < minWeight:
            minNode = node
            minWeight = d[node]
    Q.remove(minNode)
    return minNode

feedback

  1. 최소신장트리를 구하는 문제라는 것을 바로 연결시키지 못했다. '최단경로'와 '최소신장트리'에 대한 개념 재정립 필요하다.
  2. 프림 혹은 크루스칼 등의 알고리즘이 떠오르지 않았다.
  3. 알고리즘을 이해해도, 실제 코드로 구현하는 데에 상당한 시간이 걸렸다.
profile
Backend Developer

0개의 댓글