Programmers

[프로그래머스 Level.2] 다리를 지나는 트럭 (스택/큐) (Java)

Devtraces 2022. 12. 29. 14:13

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/42583

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

 

코딩테스트 연습 > 스택/큐 > 다리를 지나는 트럭

 

 

문제 설명

 

 

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

 

 

 

 

나의 코드

import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        int answer = 0;
        int nowBridgeWeight = 0; // 현재 다리 위 무게
        int idx = 0; // 트럭 배열 인덱스를 나타내기 위한 변수
        
        Queue<Integer> bridgeQueue = new LinkedList<>(); // 다리 위 상태 큐
        
        while(true) {
            answer++; // 1초 경과
            
            // 경과 시간이 bridge_length 지나면 1초 경과마다 다리에서 제일 앞의 트럭 제거
            if(answer > bridge_length) 
                nowBridgeWeight -= bridgeQueue.poll();
        	
            // 남은 트럭이 있는 경우
            if(idx < truck_weights.length) {
            	// 현재 다리 위 무게 + 다음 트럭 무게가 다리 위 무게 제한 이하면
                if(nowBridgeWeight + truck_weights[idx] <= weight) {
                    bridgeQueue.add(truck_weights[idx]); // 다리 위에 트럭 추가
                    nowBridgeWeight += truck_weights[idx]; // 다리 위 무게에 추가한 트럭 무게 더함
                    idx++; // 다음 트럭 인덱스
                } else {
                    // 현재 다리 위 무게 + 다음 트럭 무게가 다리 위 무게 제한을 넘어가면 다리 위에 가상의 빈 트럭(0)을 추가
                    bridgeQueue.add(0);
                }
            }
            
            if(bridgeQueue.isEmpty()) 
            	break;
        }
        
        return answer;
    }
}

 

풀이

  1. 문제에 주어진 것만 보면 트럭이 다리 위를 지나가는데 얼마나 걸리는지에 대한 설명이 명확하지 않은데 문제 출처를 보면 알 수 있다. 한 트럭이 다리를 건너는데 필요한 시간도 bridge_length 만큼 걸린다고 한다.
  2. 우선 다리 위의 현재 무게를 나타내기 위한 int형 변수nowBridgeWeight와 트럭의 인덱스를 나타낼 int형 변수 idx를 생성한다. 그리고 다리 위에 트럭이 올라가고 내려오는 상태를 나타내기 위해 큐를 생성한다.
  3. 그리고 이제 트럭이 다 지나갈 때까지 while문을 돌려주면 된다.
  4. while문에서는 일단 1턴에 1초씩 증가시킨다.
  5. 한 트럭이 다리를 건너는데 필요한 시간도 bridge_length 만큼 걸린다고 하니 경과 시간이 bridge_length가 지나면 다리에서 제일 앞의 트럭을 제거하도록 한다. (이렇기 때문에 1초 경과 시 무게 때문에 다음 트럭이 올라갈 수 없다면 가상의 빈 트럭(0)을 올리도록 한다.)
  6. 그리고 남은 트럭이 있는 경우 현재 다리 위 무게 + 다음 올라갈 트럭의 무게가 다리가 견딜 수 있는 무게라면 다리 위 트럭 상태를 나타내는 큐에 다음 트럭을 넣어준다. 그리고 다리 위 무게인 nowBridgeWeight에 이 트럭 무게를 더해주고 idx를 1 증가시켜 그 다음 트럭을 가리키도록 한다.
    현재 다리 위 무게 + 다음 올라갈 트럭의 무게를 다리가 견딜 수 없는 무게라면 큐에 빈 트럭(0)을 넣어준다. 트럭마다 경과시간을 따로 세는게 아니라 전체적으로 관리할 것이기 때문에 경과 시간이 nowBridgeWeight를 지나면 큐에서 무조건 하나씩 제거하기 위해서이다.
  7. 남은 트럭도 없고 다리 위에도 아무것도 없다면 while문을 종료하고 경과 시간을 리턴하면 된다.