[Python] 2887 - 행성 터널

2025. 7. 11. 19:22·Coding-Test/백준
728x90
반응형

[Platinum V] 행성 터널 - 2887 

[문제 링크](https://www.acmicpc.net/problem/2887)

🗝️알고리즘 분류

  • 그래프 탐색
  • 최소 스패닝 트리

💻문제 정의

3차원 좌표 위의 한 점은 행성의 위치이다. 이때 각 행성 사이의 터널을 연결할 때, 필요한 최소 비용을 구하는 프로그램을 작성하는 문제이다.

 

💡접근 및 설계

최소 스패닝 트리를 이용하여 최소 비용 트리를 구현하였다. Union-Find 방식을 이용하여 트리를 간단하게 구현할 수 있다.

def get_parent(x):
    if (parent[x] == x):
        return x

    parent[x] = get_parent(parent[x])

    return parent[x]

def union_parent(a, b):
    a = get_parent(a)
    b = get_parent(b)

    if (a < b):
        parent[b] = a

    else:
        parent[a] = b

def same_parent(a, b):
    return get_parent(a) == get_parent(b)

 

✏️알고리즘 풀이

tree = []

# 각 차원(x, y, z)에 대해
for dim in range(3):
    # 해당 축에 대해 정렬: (좌표값, 노드번호)
    sorted_pos = sorted([(position[i][dim], i) for i in range(1, N+1)])

    # 인접한 노드끼리 간선 연결
    for i in range(N - 1):
        a_idx = sorted_pos[i][1]
        b_idx = sorted_pos[i + 1][1]
        weight = abs(sorted_pos[i][0] - sorted_pos[i + 1][0])
        tree.append([a_idx, b_idx, weight])

문제에선 3차원의 좌표가 주어진다. 두 점의 거리는 x, y, z 좌표의 각각의 차들 중 최솟값이다. 

축을 기준으로 정렬 후, 인접한 점들끼리 간선을 이어 트리를 구성한다.

 

N=5일때, 한 축당 간선 4개 * 3축으로 총 12개의 간선으로 이루어진 트리가 완성된다.

 

## 실패 코드 (메모리 초과)

tree = []
for i in range(1, N):
    for j in range(2, N+1):
        if (i == j):
            continue
        x = abs(position[i][0] - position[j][0])
        y = abs(position[i][1] - position[j][1])
        z = abs(position[i][2] - position[j][2])
        weight = min(x, y, z)

        tree.append([i, j, weight])

처음에는 단순무식하게 모든 좌표에 대해서 최솟값을 weight로 두어 간선을 구성하였으나, N의 범위는 최대 10만으로 간선의 수는 최대 5,000,000,000개가 될 수 있다.

 

따라서 간선의 추가 방식에서 최적화가 필요하였다.

 

🗒️제출 코드

# 2887 행성 터널

N = int(input())

position = [[]]
for _ in range(N):
    x, y, z = map(int, input().split())
    position.append([x, y, z])

tree = []

# 각 차원(x, y, z)에 대해
for dim in range(3):
    # 해당 축에 대해 정렬: (좌표값, 노드번호)
    sorted_pos = sorted([(position[i][dim], i) for i in range(1, N+1)])

    # 인접한 노드끼리 간선 연결
    for i in range(N - 1):
        a_idx = sorted_pos[i][1]
        b_idx = sorted_pos[i + 1][1]
        weight = abs(sorted_pos[i][0] - sorted_pos[i + 1][0])
        tree.append([a_idx, b_idx, weight])

tree.sort(key = lambda x : x[2])

parent = [i for i in range(N+1)]

def get_parent(x):
    if (parent[x] == x):
        return x

    parent[x] = get_parent(parent[x])

    return parent[x]

def union_parent(a, b):
    a = get_parent(a)
    b = get_parent(b)

    if (a < b):
        parent[b] = a

    else:
        parent[a] = b

def same_parent(a, b):
    return get_parent(a) == get_parent(b)

answer = 0
for a, b, cost in tree:
    if not (same_parent(a, b)):
        union_parent(a, b)
        answer += cost

print(answer)

💭오늘의 회고

처음으로 풀어본 플래티넘 문제이다.

 

확실히 지금까지의 문제와는 다르게, 시간 복잡도나 메모리 관련해서 조금 더 신경을 많이 써야겠다는 생각을 하였다.

문제 구현 난이도 자체는 크게 달라진 바 없으나, 해당 문제처럼 단순 반복에서 메모리 관리를 해주어야 한다는 것을 깨달았고, 그에맞게 더욱 효율적인 알고리즘을 선택해야 한다는 것을 배웠다.

 

갈 길이 아직 멀다...

728x90
반응형
저작자표시 (새창열림)

'Coding-Test > 백준' 카테고리의 다른 글

[Python] 17070 - 파이프 옮기기 1  (0) 2025.07.13
[Python] 2096 - 내려가기  (0) 2025.07.13
[Python] 1106 - 호텔  (1) 2025.07.06
[Python] 1916 - 최소비용 구하기  (0) 2025.07.04
[Python] 7662 - 이중 우선순위 큐  (0) 2025.06.27
'Coding-Test/백준' 카테고리의 다른 글
  • [Python] 17070 - 파이프 옮기기 1
  • [Python] 2096 - 내려가기
  • [Python] 1106 - 호텔
  • [Python] 1916 - 최소비용 구하기
희완
희완
희완한 코딩일상
    반응형
  • 희완
    Code-Heewan
    희완
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Python
        • 가상환경
      • Algorithm
      • Coding-Test
        • 백준
        • 프로그래머스
        • 항해99
      • Data-Analysis
      • 웹 개발
        • django
      • AWS
      • 공모전
      • Mobile
  • 링크

    • Github
  • 300x250
  • hELLO· Designed By정상우.v4.10.3
희완
[Python] 2887 - 행성 터널
상단으로

티스토리툴바