💡Problem Solving/Programmers

[프로그래머스] 다리를 지나가는 트럭 (Java)

gom20 2021. 10. 20. 14:26

#문제

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

 

코딩테스트 연습 - 다리를 지나는 트럭

트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 다리에는 트럭이 최대 bridge_length대 올라갈

programmers.co.kr


#풀이

Queue 자료 구조를 사용하였고 Bridge, Truck을 클래스로 구현하였다. 

다리 위에 트럭이 모두 빠져나갈때까지 시간을 1초씩 증가시키며

진입 조건, 진출 조건을 체크하여 트럭을 진입 / 진출 시킨다. 

 

#소스코드

import java.util.*; 

class Bridge{
    Queue<Truck> que;
    int totalWeight;
    int limit;
    int bridge_length;
    
    public Bridge(int bridge_length, int limit){
        this.que = new LinkedList<Truck>();   
        this.totalWeight = 0;
        this.limit = limit;
        this.bridge_length = bridge_length;
    }
    
    public void offer(Truck t){
        // 트럭이 다리 위로 진입한다. 
        // 해당 트럭의 무게를 전체 무게에 더해준다.
        que.offer(t);
        totalWeight += t.weight;
    }
    
    public Truck poll(){
        // 트럭이 다리 위를 빠져나간다. 
        // 해당 트럭의 무게를 전체 무게에서 뺴준다.
        Truck t = que.poll();
        totalWeight -= t.weight;
        return t;
    }
    
    public boolean canOffer(int weight){
        // 현재 다리 위에 있는 트럭무게의 합 + 진입할 트럭의 무게가 다리 하중보다 크면 진입이 불가능하다.
        // 현재 다리 위에 있는 트럭의 개수가 다리 길이와 동일하다면 다리가 꽉 찬것이므로 진입이 불가능하다.
        if(totalWeight + weight > limit) return false;
        if(que.size() == bridge_length) return false;
        return true;
    }
    
    public boolean canPoll(int curTime){
        // 트럭이 다리 출구에 도착했는지 체크한다.
        // 현재 시각 - 진입 시각이 다리 길이 이상이 되면 다리를 모두 통과한 것이다. (1초에 1씩 움직이므로)
        if(curTime - que.peek().enterTime >= bridge_length) return true;
        return false;
    }
    
}

class Truck {
    int weight;
    int enterTime;
    
    public Truck(int weight, int enterTime){
        // 트럭은 트럭의 무게와 진입 시간을 멤버 변수로 가진다.
        this.weight = weight;
        this.enterTime = enterTime;
    }
}

class Solution {
    public int solution(int bridge_length, int limit, int[] truck_weights) {
        // 트럭의 무게를 Queue에 넣어서 들고 있는다.
        Queue<Integer> tw = new LinkedList<Integer>();
        for(int i = 0; i < truck_weights.length; i++){
            tw.offer(truck_weights[i]);
        }
        
        // 첫번째 트럭을 진입시킨다.
        int curTime = 0;
        Bridge bridge = new Bridge(bridge_length, limit);
        bridge.offer(new Truck(tw.poll(), curTime));

        // 다리위의 트럭이 모두 없어질 때까지 1초 간격으로 조건을 체크한다.
        while(!bridge.que.isEmpty()){
            // 현재 시각에 다리 위에 빠져나갈 트럭이 있는지 체크하여, 있다면 트럭을 제거한다.
            if(bridge.canPoll(curTime)) bridge.poll();            
            
            // 다리 위에 진입이 가능한지 체크하여, 가능하면 트럭을 진입시킨다.
            if(!tw.isEmpty() && bridge.canOffer(tw.peek())){
                bridge.offer(new Truck(tw.poll(), curTime));
            }
            
            // 1초 경과
            curTime++;
        }
        
        return curTime;
    }
}