[알고리즘][2] 다리를 지나는 트럭

2023. 8. 9. 10:45알고리즘 풀이

문제 설명
트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 다리에는 트럭이 최대 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
출처

※ 공지 - 2020년 4월 06일 테스트케이스가 추가되었습니다.

나의 풀이

- 풀긴 풀었다. 그러나 코드가 지저분

from collections import deque

def solution(bridge_length, weight, truck_weights):
    # 시뮬레이션 문제
    # 시간을 기준으로 해야할까? 다리를 기준으로 해야할까?
    # 시간을 기준으로 하자 그게 지금 더 명확하다
    
    bridge_loc = deque([0] * bridge_length)
    # 다리의 상황: 트럭의 위치, 트럭들의 weight 합
    bridge = [bridge_loc, 0]
    
    time = 0
    while True:
        
        
        cur_bridge_loc, cur_bridge_weight = bridge
        
        if not truck_weights and cur_bridge_weight == 0:
            break
        
        time += 1
        if truck_weights:
            # 현재 트럭
            cur_truck_weight = truck_weights[0]
            leave_truck_weight = cur_bridge_loc.popleft()
            cur_bridge_weight -= leave_truck_weight
            
            # 만약 새 트럭이 진입할 수 없다면 현재 트럭의 위치만 이동
            if cur_truck_weight + cur_bridge_weight > weight:
                
                bridge[1] -= leave_truck_weight
                cur_bridge_loc.append(0)
            # 진입할 수 있다면 새로운 트럭 추가
            else:
                bridge[1] -= leave_truck_weight
                truck_weights.pop(0)
                cur_bridge_loc.append(cur_truck_weight)
                bridge[1] += cur_truck_weight
        else:
            leave_truck_weight = cur_bridge_loc.popleft()
            bridge[1] -= leave_truck_weight
            cur_bridge_loc.append(0)
            
        
    return time

리팩토링한 코드

- if 문의 주체를 바꿨다. 또한 if문을 한번만 써서 표현하니 else문도 한번만 필요해졌다. (동일한 블록을 두개의 else에 똑같이 넣을 필요가 없어졌다)

- 공통된 코드는 묶었다.

- bridge라는 배열로 묶지 않고 bridge_loc, bridge_weight로 명확하게 해주었다.

from collections import deque

def solution(bridge_length, weight, truck_weights):
    # 시뮬레이션 문제
    # 시간을 기준으로 해야할까? 다리를 기준으로 해야할까?
    # 시간을 기준으로 하자 그게 지금 더 명확하다
    
    bridge_loc = deque([0] * bridge_length)
    bridge_weight = 0
    # 다리의 상황: 트럭의 위치, 트럭들의 weight 합
    
    time = 0
    while True:
        
        # 남은 트럭이 없고 다리 위에 트럭이 없다면 끝
        if not truck_weights and bridge_weight == 0:
            break
        
        time += 1
        
        # 다리 위에 트럭이 있다면 다리의 상황을 한칸씩 조정
        leave_truck_weight = bridge_loc.popleft()
        bridge_weight -= leave_truck_weight
        
        # 진입할 수 있다면 새로운 트럭 추가
        if truck_weights and truck_weights[0] + bridge_weight <= weight:
            # 현재 트럭
            cur_truck_weight = truck_weights[0]
            truck_weights.pop(0)
            bridge_loc.append(cur_truck_weight)
            bridge_weight += cur_truck_weight
        # 만약 새 트럭이 없거나 진입할 수 없다면 현재 트럭의 위치만 이동
        else:
            bridge_loc.append(0)
            
        
    return time

'알고리즘 풀이' 카테고리의 다른 글

[알고리즘][2] H-Index  (0) 2023.08.11
[알고리즘][2] 가장 큰 수  (0) 2023.08.10
[알고리즘][2][X] 기능개발  (0) 2023.08.08
[알고리즘][X] 방의 개수  (0) 2023.08.07
[알고리즘][X] 순위  (0) 2023.08.02