프로그래머스 - 다리를 지나는 트럭 (스택/큐)
이번 포스팅에서는 프로그래머스의 다리를 지나는 트럭(스택/큐) 코딩테스트 연습 문제를 풀어봅니다.
문제 설명
트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 다리에는 트럭이 최대 bridge_length대 올라갈 수 있으며, 다리는 weight 이하까지의 무게를 견딜 수 있습니다. 단, 다리에 완전히 오르지 않은 트럭의 무게는 무시합니다.
예를 들어, 트럭 2대가 올라갈 수 있고 무게를 10kg까지 견디는 다리가 있습니다. 무게가 [7, 4, 5, 6]kg인 트럭이 순서대로 최단 시간 안에 다리를 건너려면 다음과 같이 건너야 합니다.
경과 시간 | 다리를 지난 트럭 | 다리를 건너는 트럭 | 대기 트럭 |
---|---|---|---|
0 | [] | [] | [7,4,5,6] |
1~2 | [] | [7] | [4,5,6] |
3 | [7] | [4] | [5,6] |
4 | [7] | [4,5] | [6] |
5 | [7,4] | [5] | [6] |
6~7 | [7,4,5] | [6] | [] |
8 | [7,4,5,6] | [] | [] |
따라서, 모든 트럭이 다리를 지나려면 최소 8초가 걸립니다.
solution 함수의 매개변수로 다리에 올라갈 수 있는 트럭 수 bridge_length, 다리가 견딜 수 있는 무게 weight, 트럭 별 무게 truck_weights가 주어집니다. 이때 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 return 하도록 solution 함수를 완성하세요.
제한조건
- bridge_length는 1 이상 10,000 이하입니다.
- weight는 1 이상 10,000 이하입니다.
- truck_weights의 길이는 1 이상 10,000 이하입니다.
- 모든 트럭의 무게는 1 이상 weight 이하입니다.
입출력 예
bridge_length | weight | truck_weights | return |
---|---|---|---|
2 | 10 | [7,4,5,6] | 8 |
100 | 100 | [10] | 101 |
100 | 100 | [10,10,10,10,10,10,10,10,10,10] | 110 |
문제 풀이
먼저 대기 트럭과 진행 트럭의 리스트를 따로 관리 하였습니다.
다리 중량을 넘기 전이면 대기트럭의 맨 앞 트럭을 진행 트럭 리스트에 추가합니다.
진행 트럭 리스트의 맨 앞 트럭이 경과시간이 지나면 리스트에서 제외 합니다.
일련의 반복문이 한번 돌때 마다 전체 경과 시간은 1씩 증가하며 진행 트럭은 경과 시간을 따로 관리하여 전체 경과 시간이 1씩 증가 할때 마다 진행 시간은 1씩 감소합니다.
진행 트럭 리스트의 맨 앞 트럭의 경과시간이 0이 되면 완료 트럭 임으로 리스트 에서 제외합니다.
대기 트럭이 더 이상 존재 하지 않고 건너가는 트럭만 남으면 진행 트럭 리스트의 마지막 트럭이 지나갈때 일련의 과정이 끝남으로 전체 경과 시간에 마지막 트럭의 남은 경과 시간을 더해 줍니다.
위의 과정 만으로도 원하는 결과를 얻을 수는 있지만 다리 중량을 넘었을때 진행 트럭 리스트가 유지되며 경과 시간이 올라 가는데 이는 전체 반복문이 비 효율적으로 반복 하게 되어 있음으로
다리 중량을 넘었을 때는 진행 트럭 리스트의 맨 앞 트럭의 남은 경과 시간을 리스트 각 요소마다 빼주고 전체 경과 시간에 더해줌으로서 많은 연산을 줄여 줄 수 있습니다.
from collections import deque
def solution(bridge_length, weight, truck_weights):
wait_trucks = deque(truck_weights)
proc_trucks = deque()
answer = 0
proc_weight = 0
while wait_trucks: # 대기 트럭 상황
# 기존 진행 트럭은 1초 마다 감소
for p in proc_trucks:
p[0] -= 1
# 맨 앞의 진행 트럭이 경과시간이 지나면 리스트에서 제외
if len(proc_trucks):
if proc_trucks[0][0] == 0:
pt = proc_trucks.popleft()
proc_weight -= pt[1]
fwt = wait_trucks[0]
sum_tw = proc_weight + fwt
if sum_tw <= weight: # 다리 중량을 넘기전
# 대기 트럭을 진행 트럭으로 변환
wt = wait_trucks.popleft()
proc_truck = [bridge_length, wt]
proc_trucks.append(proc_truck)
proc_weight += wt
else: # 다리 중량을 넘겼을때(연산을 줄여 줌)
ptime = proc_trucks[0][0] - 1
for p in proc_trucks:
p[0] -= ptime
answer += ptime
answer += 1
# 대기 트럭이 존재 하지 않고 건나가는 트럭만 남았을때
pt = proc_trucks.pop() # 마지막에 들어온 트럭
answer += pt[0] # 마지막 트럭의 경과사간을 더해줌
return answer
ret = solution(2, 10, [7,4,5,6])
print(ret)
ret = solution(100, 100, [10])
print(ret)
ret = solution(100, 100, [10,10,10,10,10,10,10,10,10,10])
print(ret)
8
101
110
결과는 아래와 같이 잘 통과 되는 것을 확인 할 수 있습니다.