[프로그래머스 - 스택/큐] 다리를 지나는 트럭

    🔍문제

    문제 설명

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

    처음에 읽었을 때 너무 이해가 안가서 차근차근 정리하면서 문제를 이해해보았다.

    • 목표: 모든 트럭이 다리를 건너는 데 최소 시간을 계산하여라.
    • 조건:
      • 최대 트럭 수: bridge_length
      • 최대 무게: weight(다리에 온전히 올라가지 않은 트럭의 무게는 포함X)
      • 트럭 별 무게: truck_weights

    입출력 예를 보고도 이해안돼서 질문목록을 참고하였다.

    10kg 제한인 다리에 7kg 트럭이 있으면 어떻게 나오는건지 했는데 1초에 한 칸씩 움직인단다…

    나같은 사람들이 많은가보다…

     

    🤩 입출력 예시 정리

    다리 길이가 2라면

    초기 상태 [0, 0]

    1초 [0, 7]

    2초 [7, 0]

    3초 [0, 4]

    4초 [4, 5]

    5초 [5, 0]

    6초 [0, 6]

    7초 [6, 0]

    8초 [0, 0]

    이렇게 총 8초가 걸린다는 말이었다. 무슨 문제를 이렇게 설명하냐

     

    💡 풀이 과정

    import queue
    
    def solution(bridge_length, weight, truck_weights):
        time = 0
        bridge = [0] * bridge_length    # 다리의 위치
        total_weight = 0    # 다리 위의 무게
        waiting_truck = truck_weights[:]    #대기중인 트럭
        
        while waiting_truck or total_weight > 0:
            time += 1
            total_weight -= bridge.pop(0)   # 트럭이 하나 건너가면 다리 위의 무게를 감소
            if waiting_truck:   # 대기중인 트럭이 있다면
                # 다리 위의 무게 + 다음 트럭의 무게 <= 다리가 견딜 수 있는 무게라면
                if total_weight + waiting_truck[0] <= weight:
                    truck_weight = waiting_truck.pop(0)      # 다음 트럭을 불러옴
                    bridge.append(truck_weight)     # 다음 트럭을 다리 위에 놓음
                    total_weight += truck_weight    # 기존 다리 위의 무게 + 다음 트럭 무게 갱신
                else:   # 다리에 트럭이 못 올라가는 경우
                    bridge.append(0)
        return time
    

     

     


    🌟 최종 코드

    import queue
    
    def solution(bridge_length, weight, truck_weights):
        time = 0
        bridge = [0] * bridge_length    
        total_weight = 0  
        waiting_truck = truck_weights[:]   
        
        while waiting_truck or total_weight > 0:
            time += 1
            total_weight -= bridge.pop(0)   
            if waiting_truck:  
                if total_weight + waiting_truck[0] <= weight:
                    truck_weight = waiting_truck.pop(0)      
                    bridge.append(truck_weight)     
                    total_weight += truck_weight   
                else: 
                    bridge.append(0)
        return time
    

     

     

     


    💡 추가 코드

    보통 다들 보니까 deque를 이용해서 풀었다.

    Queue (큐)

    • 정의: 큐는 선형 자료구조의 한 종류로, 데이터가 들어간 순서대로 처리되는 특성을 가지고 있다.
    • 작동 원리: 큐는 FIFO (First In, First Out) 원칙을 따른다.
    • 주요 연산:
      • enqueue: 큐의 끝(뒤)에 데이터를 추가하는 연산.
      • dequeue: 큐의 앞에서 데이터를 제거하고 반환하는 연산.
    • 사용 예시: 작업 대기열, 프린터 작업 관리 등 순서대로 처리가 필요한 경우.

    Deque (덱, Double-Ended Queue)

    • 정의: 덱은 큐의 확장형으로, 양쪽 끝에서 모두 삽입과 삭제가 가능한 선형 자료구조.
    • 작동 원리: 덱은 양쪽 끝에서 모두 삽입과 삭제가 가능한 구조이다.
    • 주요 연산:
      • append: 덱의 끝(뒤)에 데이터를 추가하는 연산.
      • appendleft: 덱의 시작(앞)에 데이터를 추가하는 연산.
      • pop: 덱의 끝(뒤)에서 데이터를 제거하고 반환하는 연산.
      • popleft: 덱의 시작(앞)에서 데이터를 제거하고 반환하는 연산.
    • 사용 예시: 캐시 구현, 슬라이딩 윈도우 문제 등 양방향 접근이 필요한 경우.

    Queue와 Deque의 차이점

    • 작동 방식:
      • Queue: 한쪽 끝에서만 삽입이 가능하고, 반대쪽 끝에서만 삭제가 가능한 구조. (단방향)
      • Deque: 양쪽 끝에서 삽입과 삭제가 모두 가능한 구조. (양방향)
    • 유연성:
      • Queue: 입출력 방식이 고정되어 있어, 순차적으로 처리해야 하는 상황에 최적화되어 있다.
      • Deque: 양쪽 끝에서 입출력 작업이 가능해, 다양한 상황에 유연하게 대응할 수 있다.
    from collections import deque
    
    def solution(bridge_length, weight, truck_weights):
        bridge = deque(0 for _ in range(bridge_length)) 
        #0 for _ in ...: _는 변수명을 사용하지 않겠다는 의미로, 각 반복마다 0을 생성
        total_weight = 0
        step = 0
        truck_weights.reverse()
    
        while truck_weights:
            total_weight -= bridge.popleft()
            if total_weight + truck_weights[-1] > weight:
                bridge.append(0)
            else:
                truck = truck_weights.pop()
                bridge.append(truck)
                total_weight += truck
            step += 1
    
        step += bridge_length
    
        return step
    

    댓글