devFancy BE Developer

[Programmers] 42583. 다리를 지나는 트럭

2023-04-03
devFancy

문제 링크

성능 요약

  • 메모리: 77.2 MB, 시간: 0.09 ms

구분

  • 코딩테스트 연습 > 스택/큐

Answer Code1(23.04.03)

/**
 * bridge_length : 다리에 올라갈 수 있는 트럭 수
 * weight : 다리가 견딜 수 있는 무게
 * truck_weights : 트럭 별 무게
 */

import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        Queue<Integer> queue = new LinkedList<>();
		int sum = 0; // 현재 다리를 건너는 트럭 무게의 합
		int time = 0; // 모든 트럭이 다리를 건너는 최소의 시간

		for(int i = 0; i < truck_weights.length; i++) { // 향상된 for문을 쓰는게 좋을 것 
			int truck = truck_weights[i];

			while(true) {
				// [1] 큐가 비어있는 경우 = 어떠한 트럭도 다리위에 없는 경우
				if(queue.isEmpty()) { 
					queue.add(truck);
					sum += truck;
					time++; // 다리에 오를 때만 시간 추가 
					break;
				} else if(queue.size() == bridge_length) { // [2] 큐가 가득찬 경우
					sum -= queue.poll();
				} else  { // [3] 큐가 다리 길이만큼 가득 차지 않는 경우
					// weight 값을 넘지 않는 선에서 새로운 트럭을 다리에 올려줌 
					if(sum + truck <= weight) {
						queue.add(truck);
						sum += truck;
						time++;
						break;
					} else { 
						// weight 값을 넘는다면, 0을 넣어 이미 큐에 있는 트럭이 다리를 건너게 만듬 
						queue.add(0);
						time++;
					}
				}
			}
		}

        // 마지막 트럭에서 반복문이 끝나는데, 마지막 역시 다리 길이만큼 지나가야 하기 때문에, 다리 길이만큼 더해준다.
		return time + bridge_length; 
    }
}

문제 풀이 - Answer Code1

  • 트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 한다. => 를 사용한다.

  • 큐를 다리라고 생각하고, 조건에 맞게 트럭을 큐에 넣고 빼면서 최소 몇 초가 걸리는 지 return 하면 되는 문제였다.

  • 고려해야할 사항

    • 다리에는 트럭이 최대 bridge_length대 올라갈 수 있고, 다리는 weight 이하까지의 무게를 견딜 수 있다.

    • 다리에 완전히 오르지 않는 트럭의 무게는 무시한다 == 다리를 건너는 트럭의 무게만 측정한다 => 같은 의미.

    • 트럭이 다리에 올라가면 1초가 시작되고, 다리 위에서 1칸씩 움직일 때마다 역시 1초가 흘러간다.

  • 다리에 트럭을 넣는 조건은 총 3가지다.

    • [1] 큐가 비어있는 경우 -> 트럭을 다리에 올려준다 (시간은 +1 증가)

    • [2] 큐가 가득찬 경우 -> 이때는 가장 앞에 넣은 트럭이 다리의 끝에 도달했다는 의미이므로 poll() 메서드를 이용해 트럭을 꺼내 줌으로써, 다리를 건너가도록 한다. 이때 다리에서 내릴 때는 시간이 들지 않는다.

    • [3] 큐가 다리 길이만큼 가득 차지 않는 경우 -> 큐에 이미 있는 트럭에 다리를 지나갈 수 있도록 0 값을 넣어준다. (시간은 +1 증가)

  • 이 과정을 전체 트럭의 개수만큼 반복한다.

  • 위의 반복문의 특성상 마지막 트럭의 경우 다리에는 올랐지만 다 건너지는 못한다. 그래서 정답을 출력할 때는 지금까지 걸린 time에서 마지막 트럭이 건너는데 걸리는 시간인 다리의 길이를 더해서 출력하면 된다.

Answer Code2(23.12.18)

// 다리를 지나는 트럭(23.12.18) - 1차 복습
import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        int sum = 0; // 현재 다리를 지나는 트럭 무게의 합
        int time = 0; // 모든 트럭이 다리를 건너는 최소 시간의 합(걸린 시간)

        Queue<Integer> bridgeQueue = new LinkedList<>(); // 다리를 지나기 전 트럭
        for(int truck : truck_weights) {
        
            while(true) {
                // 1. 큐가 비어있는 경우 트럭 추가
                if(bridgeQueue.isEmpty()) {
                    bridgeQueue.offer(truck);
                    sum += truck;
                    time++; // 다리에 오를 때만 시간 추가 
                    break;
                }
                // 2. 다리에 건너는 트럭 무게의 합 == 견딜 수 있는 최대무게(weight)
                else if(bridgeQueue.size() == bridge_length) {
                    sum -= bridgeQueue.poll();
                }

                // 3. 큐가 비어있지 않은 경우
                else {
                    // 2-2. (다음 트럭까지 포함하여) 다리에 건너는 트럭 무게의 합 > 견딜 수 있는 최대 무게
                    if(sum + truck > weight) {
                        bridgeQueue.offer(0);
                        time++;
                    }
                    // 2-3. (다음 트럭까지 포함하여) 다리에 건너는 트럭 무게의 합 < 견딜 수 있는 최대 무게
                    else {
                        bridgeQueue.offer(truck);
                        sum += truck;
                        time++;
                        break;
                    }

                }
            }
        }
        // 걸린 시간 + 마지막 트럭의 통과 시간
        return time + bridge_length;
    }
}

Review

  • 큐를 이용해서 문제를 풀어야 겠다는 생각은 가졌지만, 경우의 수를 생각하는 데 있어서 어려움이 있었다.

  • 단순히 머리로만 생각하지말고, 뭔가 생각할 게 많다고 생각하면 그림을 그리면서 풀어가는 습관을 가지도록 하자.

Reference


Comments

Index