알고리즘 스터디

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

cme10575 2021. 2. 28. 01:11

문제

 


풀이

처음에 두 가지 방법의 풀이가 떠올랐다.

1. 다리를 지나는 트럭 큐를 만든다. 반복문을 통해 트럭을 넣고, 중량의 합이 커 다음 트럭이 지나갈 수 없을 때에는 0을 채워넣으며 time을 +1씩 증가시킨다. 모든 트럭이 통과했을 때의 time을 반환한다.

2. 위와 같은 방식이지만, 트럭이 지나갈 수 없을 때 0을 채워넣으며 반복시키는 대신, 트럭이 들어온 시간을 저장해두었다가 가장 먼저 들어온 트럭을 내보내고 그만큼의 time을 더해준다.

이 방식은 반복문이 돌아가는 횟수를 줄여주어 값이 커지면 보다 좋은 효율을 보여줄 것이라 예상했다.

 

그래서 2번방식으로 코드를 작성하였는데 구연하다가 포기함. 복잡함,,,

from collections import deque

def solution(bridge_length, max_weight, truck_weights):
    time = 1
    bridge = deque()
    bridge.append([0, 1])
    weight = truck_weights[0]
    truck_idx = 1
    
    while True:
        print(time, bridge)
        # 종료조건
        if truck_idx >= len(truck_weights) and not bridge:
            return time
        # 다 건넌 트럭 빼기
        if bridge[0][1] + bridge_length < time:
            print("first")
            weight -= truck_weights[bridge[-1][0]]
            bridge.popleft()    
        # 다음 트럭 넣기
        if truck_idx < len(truck_weights) and weight + truck_weights[truck_idx] <= max_weight:
            bridge.append([truck_idx, time])
            weight += truck_weights[truck_idx]
            truck_idx += 1
            time += 1
        # 다음 트럭 못넣으면 시간추가하고 트럭빼기
        elif truck_idx < len(truck_weights):
            print("second")
            time = bridge[0][1] + bridge_length
            print(time)
            weight -= truck_weights[bridge[0][0]]
            bridge.popleft()
       
    return time

그래서 다시 1번 방식으로 했다. 이러니까 금방풀었다 근데 느린 것 같음

def solution(bridge_length, max_weight, truck_weights):
    time = 0
    bridge = [0] * bridge_length
    
    while True:
        if len(truck_weights) <= 0 and sum(bridge) == 0:
            return time
        bridge.pop(0)
        if truck_weights and sum(bridge) + truck_weights[0] <= max_weight:
            bridge.append(truck_weights.pop(0))
        else:
            bridge.append(0)
        time += 1
    
    return time

deque는 0번째 요소를 삭제하는데 리스트보다 빠르기때문에 deque로 수정해봤다

 

from collections import deque

def solution(bridge_length, max_weight, truck_weights):
    time = 0
    truck_weight_deque = deque(i for i in truck_weights)
    bridge = deque(0 for _ in range(bridge_length))
    
    while bridge:
        bridge.popleft()
        if truck_weight_deque:
            if sum(bridge) + truck_weight_deque[0] <= max_weight:
                bridge.append(truck_weight_deque.popleft())
            else:
                bridge.append(0)
        time += 1
    
    return time

띠용? 전체적으로 빨라졌는데 5번에서 시간초과;; 왜인지는 모르겠다.

 

번외로 예전에 c++로 풀어놓은 코드가 있어 가져왔다.

#include <string>
#include <vector>
#include <iostream>

using namespace std;

int solution(int bridge_length, int weight, vector<int> truck_weights) {
    vector<int> cross_bridge(truck_weights.size());
    int start = 0;
    int end = 0;
    int time = 1;
    int now_weight = truck_weights[0];
    cross_bridge[0] = 1;
    
    while(true) {
        
        if(start >= truck_weights.size()) {
            break;
        }
        
        if(cross_bridge[start] >= bridge_length) {
            now_weight -= truck_weights[start];
            start++;
        }
        
        time++;
        
        if(end < truck_weights.size() - 1) {
            if(now_weight + truck_weights[end + 1] <= weight) {
                end++;
                now_weight += truck_weights[end];
            }
        }
                
        for(int i = start; i <= end; i++) {
            cross_bridge[i]++;
        }
    }
    return time;
}

이건 더미데이터 0을 추가하는 방식이 아니고 다리를 건넌지 얼마나 되었는지 cross_bridge에 저장하고 몇 번째 트럭부터 몇 번째 트럭까지 건너고있는지 start, end에 저장하여 다리를 건너면 start, end의 위치를 조정하여 풀었다.

딱히 효율적인 방식은 아닌 것 같지만 특이한 풀이인 것 같다.

 

나중에,,, 파이썬을 잘 다루게 되면 1번 방식으로 수정해 보고 싶다.