문제 이해
트럭 여러 대가 일차선 다리를 건너려고 한다. 다리에는 무게 제한과 길이 제한이 있어서, 모든 트럭이 안전하게 건너는 데 걸리는 최소 시간을 구해야 한다.
문제 조건
- bridge_length: 다리 길이 (트럭이 다리를 건드는 데 걸리는 시간)
- weight: 다리가 견딜 수 있는 최대 무게
- truck_weights: 트럭들의 무게 배열 (순서대로 출발)
핵심 규칙
- 트럭들은 주어진 순서대로만 출발 가능 (새치기 불가)
- 모든 트럭의 속도는 동일 (1초에 1칸)
- 다리 위 트럭들의 총 무게 ≤ weight 조건 유지
- 트럭은 다리에 동시에 여러 대 있을 수 있음
첫 번째 버전: 클래스 + 큐 2개 사용
class Truck {
int weight;
int exitTime;
Truck(int weight, int exitTime) {
this.weight = weight;
this.exitTime = exitTime;
}
}
Queue<Integer> waitingQueue = new LinkedList<>();
Queue<Truck> bridgeQueue = new LinkedList<>();
두 번째 버전: 큐 안에 정수형 배열로 관리
import java.util.*;
class Solution {
public int solution(int bridge_length, int weight, int[] truck_weights) {
Queue<int[]> bridge = new LinkedList<>(); // [무게, 나가는시간]
int index = 0; // 다음에 출발할 트럭 인덱스
int time = 0;
int currentWeight = 0; // 다리 위 트럭들의 총 무게
while (index < truck_weights.length || !bridge.isEmpty()) {
time++;
// 1. 다리에서 나갈 트럭들 제거
while (!bridge.isEmpty() && bridge.peek()[1] == time) {
int[] exitTruck = bridge.poll();
currentWeight -= exitTruck[0];
}
// 2. 새 트럭이 들어갈 수 있는지 체크
if (index < truck_weights.length) {
int nextTruckWeight = truck_weights[index];
if (currentWeight + nextTruckWeight <= weight) {
// 새 트럭 출발
bridge.offer(new int[]{nextTruckWeight, time + bridge_length});
currentWeight += nextTruckWeight;
index++;
}
}
}
return time;
}
}
장단점 비교
첫 번째 버전의 장점
- 가독성: truck.weight, truck.exitTime으로 명확한 의미 전달
- 타입 안정성: 컴파일 타임에 오류 검출 가능
- 객체지향적: 데이터와 관련된 로직을 묶어서 관리 가능
첫 번째 버전의 단점
- 메모리 오버헤드: 객체 생성 비용, 추가 클래스 정의 필요
- 코드 복잡성: 클래스 정의 + 큐 2개 관리
- 성능: 객체 생성/소멸로 인한 GC 부담
두 번째 버전의 장점
- 메모리 효율성: 기본 타입 배열 사용으로 메모리 절약
- 코드 간결성: 클래스 정의 불필요, 큐 1개로 관리
- 성능: 객체 생성 비용 절약
- 구현 단순성: 로직이 더 직관적
두 번째 버전의 단점
- 가독성 저하: truck[0], truck[1]로 의미가 덜 명확
- 실수 가능성: 인덱스 접근 시 순서 헷갈릴 수 있음
- 확장성: 트럭 정보가 더 복잡해지면 관리 어려움
코드 상세 분석
초기화 부분
Queue<int[]> bridge = new LinkedList<>(); // [무게, 나가는시간]
int index = 0; // 다음에 출발할 트럭 인덱스
int time = 0; // 현재 시간
int currentWeight = 0; // 다리 위 트럭들의 총 무게
- bridge: 다리 위에 있는 트럭들의 정보 저장
- index: 아직 출발하지 않은 트럭들 중 다음 순서 추적
- currentWeight: 매번 계산하지 않고 변수로 관리해 성능 향상
메인 루프
while (index < truck_weights.length || !bridge.isEmpty()) {
time++;
// ...
}
종료 조건:
- index < truck_weights.length: 아직 출발 안한 트럭이 있거나
- !bridge.isEmpty(): 다리 위에 트럭이 있으면 계속 실행
트럭 제거 로직
while (!bridge.isEmpty() && bridge.peek()[1] == time) {
int[] exitTruck = bridge.poll();
currentWeight -= exitTruck[0];
}
- bridge.peek()[1] == time: 나가는 시간이 현재 시간과 같은지 확인
- while문 사용: 동시에 여러 트럭이 나갈 수 있음
- currentWeight 업데이트: 나간 트럭 무게만큼 차감
트럭 추가 로직
if (index < truck_weights.length) {
int nextTruckWeight = truck_weights[index];
if (currentWeight + nextTruckWeight <= weight) {
bridge.offer(new int[]{nextTruckWeight, time + bridge_length});
currentWeight += nextTruckWeight;
index++;
}
}
- 조건 1: index < truck_weights.length → 대기 중인 트럭이 있는가?
- 조건 2: currentWeight + nextTruckWeight <= weight → 무게 제한 OK?
- 나가는 시간 계산: time + bridge_length → 현재시간 + 다리길이
- index++: 다음 트럭으로 이동
핵심 포인트
- 시간 기반 시뮬레이션: 1초씩 시간을 증가시키며 상황 추적
- 큐(Queue) 활용: 먼저 들어간 트럭이 먼저 나가는 FIFO 구조
- 미래 시점 계산: 트럭이 언제 나갈지 미리 계산해서 저장
- 실시간 무게 관리: 다리 위 트럭들의 총 무게를 지속적으로 추적
'Java > 알고리즘' 카테고리의 다른 글
| 스텍 / 큐 : 기능개발 (0) | 2025.07.03 |
|---|---|
| 스텍 / 큐 : 프로세스 (1) | 2025.07.03 |
| 스텍 / 큐 : 주식가격 (0) | 2025.07.03 |
| 스택 / 큐 (0) | 2025.07.02 |
| 해시 (0) | 2025.06.23 |