공부하고 기록하는, 경제학과 출신 개발자의 노트

프로그래밍/코딩테스트 문제풀이

[Python] 백준 1005. ACM Craft

inspirit941 2020. 3. 14. 16:21
반응형

https://www.acmicpc.net/problem/1005

 

1005번: ACM Craft

첫째 줄에는 테스트케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 주어진다. 첫째 줄에 건물의 개수 N 과 건물간의 건설순서규칙의 총 개수 K이 주어진다. (건물의 번호는 1번부터 N번까지 존재한다)  둘째 줄에는 각 건물당 건설에 걸리는 시간 D가 공백을 사이로 주어진다. 셋째 줄부터 K+2줄까지 건설순서 X Y가 주어진다. (이는 건물 X를 지은 다음에 건물 Y를 짓는 것이 가능하다는 의미이다)  마지막 줄에는 백준이가 승리하기 위해 건

www.acmicpc.net

위상정렬 + bfs를 적용한 느낌의 문제.

 

 

import sys
import heapq
from collections import defaultdict
def solve(precede_list, build_next, time, target):
# 조건 없이 바로 만들 수 있는 건물들 찾기
queue = [(time[idx], idx) for idx in range(1, len(precede_list)) if precede_list[idx] == 0]
# 시간순서로 정렬. 가장 시간 짧은 것부터 뽑아내는 min heap 사용
heapq.heapify(queue)
while queue:
# 현재 시간에 건설 끝난 건물.
finish_time, building = heapq.heappop(queue)
# 완성한 건물이 target 건물이면 그동안 building한 시간 반환
if building == target:
return finish_time
# 지을 수 있는 다음 건물들 정보를 확인한다.
for next_possible in build_next[building]:
# 조건에 해당하는 건물 제거
precede_list[next_possible] -= 1
# 모든 조건이 해금되어 건물을 지을 수 있는 경우
# (지금까지 걸린 시간 + 건물 완성할 때까지 걸리는 시간, 건물) 을 heappush
if precede_list[next_possible] == 0:
heapq.heappush(queue, (finish_time + time[next_possible], next_possible))
test_case = int(sys.stdin.readline())
for _ in range(test_case):
N, K = map(int, sys.stdin.readline().split())
# 해당 index 건물을 짓기 위한 prerequisite 개수
precede_list = [0 for _ in range(N+1)]
# 해당 건물을 지으면 해금할 수 있는 건물 dictionary
build_next = defaultdict(list)
# 해당 index 건물을 짓는 데 걸리는 시간
time = list(map(int, sys.stdin.readline().split()))
time.insert(0, 0)
for _ in range(K):
precede, antecede = map(int, sys.stdin.readline().split())
precede_list[antecede] += 1
build_next[precede].append(antecede)
target = int(sys.stdin.readline())
print(solve(precede_list, build_next, time, target))
반응형