[SWEA 2477] 차량 정비소 (Java)

nnm·2020년 5월 28일
0
post-custom-banner

SWEA 2477 차량 정비소

문제풀이

이 문제는 키보드에 손을 얹기까지 30분 정도 걸렸던 것 같다. 시뮬레이션 문제는 그만큼 설계가 중요하다. 복잡한 시뮬레이션 문제의 경우에는 변수명 까지 거의 다 정해놓고 시작하는 것이 좋다.

  • 각 동작을 수행하는 부분을 함수화하면 순서 수정이 쉽다.
  • 보통 시뮬레이션 문제에는 예제에서 작동 방식을 구체적으로 보여주는데 각 동작이 수행되는 지점에 적절한 로그를 작성하여 예제와 동일하게 작동하는지 확인하는 것이 좋다.

지문에 나와있는 그대로를 코드로 잘 옮기기만 하면 된다. 하지만 현실에서의 수행 순서와 코드상의 순서가 달라질 수 있다.

  • 현실에서는
    • 접수창구에 도착
    • 접수완료
    • 정비창구에 도착
    • 정비완료
  • 코드상에서는
    • 접수완료 처리
    • 접수창구에 고객 배정
    • 정비완료 처리
    • 정비창구에 고객 배정

현실의 수행 순서를 구현하기 위해서는 코드 상에서는 역순으로 진행해야한다.

구현코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Solution {
	
	static class Customer {
		int customerNo;
		int receptionNo;
		int repaireNo;
		int arriveTime;
		int receptionStartTime;
		int receptionEndTime;
		int repairStartTime;
		
		Customer(int customerNo, int arriveTime) {
			this.customerNo = customerNo;
			this.arriveTime = arriveTime;
		}
	}
	
	static PriorityQueue<Customer> receptionQueue, repairQueue;
	static Customer[] receptionCounter, repairCounter;
	static int[] reception, repair;
	// 접수 창구의 개수 N, 정비 창구의 개수 M, 차량 정비소를 방문한 고객의 수 K, 지갑을 두고 간 고객이 이용한 접수 창구번호 A와 정비 창구번호 B가 주어진다.
	static int N, M, K, A, B, T, ans;
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		
		T = Integer.parseInt(br.readLine());
		
		for(int t = 1; t <= T ; ++t) {
			st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			K = Integer.parseInt(st.nextToken());
			A = Integer.parseInt(st.nextToken());
			B = Integer.parseInt(st.nextToken());
			
			ans = 0;
			
			reception = new int[N + 1];
			repair = new int[M + 1];
			receptionCounter = new Customer[N + 1];
			repairCounter = new Customer[M + 1];
			receptionQueue = new PriorityQueue<>(new Comparator<Customer>() {
				@Override
				public int compare(Customer o1, Customer o2) {
					return o1.customerNo - o2.customerNo;
				}
			});
			repairQueue = new PriorityQueue<>(new Comparator<Customer>() {
				@Override
				public int compare(Customer o1, Customer o2) {
					if(o1.receptionEndTime == o2.receptionEndTime) {
						return o1.receptionNo - o2.receptionNo;
					} else {
						return o1.receptionEndTime - o2.receptionEndTime;
					}
				}
			});

			st = new StringTokenizer(br.readLine());
			for(int n = 1 ; n <= N ; ++n) {
				reception[n] = Integer.parseInt(st.nextToken()); 
			}
			
			st = new StringTokenizer(br.readLine());
			for(int m = 1 ; m <= M ; ++m) {
				repair[m] = Integer.parseInt(st.nextToken()); 
			}
			
			st = new StringTokenizer(br.readLine());
			for(int i = 1 ; i <= K ; ++i) {
				receptionQueue.offer(new Customer(i, Integer.parseInt(st.nextToken())));
			}
			
			
			int time = 0;
			int cnt = 0;
			while(true) {
				// 접수 끝난 사람 정비창구로 보내기
				for(int i = 1 ; i <= N ; ++i) {
					if(receptionCounter[i] == null) continue;
					
					Customer c = receptionCounter[i];
					
					if(c.receptionStartTime + reception[i] <= time) {
//						System.out.println("[" + time + "]" + i + "번 접수창구에 " + receptionCounter[i].customerNo + "고객이 접수를 마쳤습니다." );
						c.receptionEndTime = time;
						repairQueue.offer(c);
						receptionCounter[i] = null;
					}
				}
				
				// 접수창구 채우기 
				for(int i = 1 ; i <= N ; ++i) {
					if(receptionCounter[i] == null) {
						if(!receptionQueue.isEmpty()) {
							if(receptionQueue.peek().arriveTime <= time) {
								receptionCounter[i] = receptionQueue.poll();
								receptionCounter[i].receptionNo = i;
								receptionCounter[i].receptionStartTime = time;
//								System.out.println("[" + time + "]" + i + "번 접수창구에 " + receptionCounter[i].customerNo + "고객이 접수를 시작했습니다." );
							}
						}
					}
				}
				
				// 정비 끝난 사람 내보내기
				for(int i = 1 ; i <= M ; ++i) {
					if(repairCounter[i] == null) continue;
					
					Customer c = repairCounter[i];
					
					if(c.repairStartTime + repair[i] <= time) {
//						System.out.println("[" + time + "]" + i + "번 정비창구 " + repairCounter[i].customerNo + "고객이 정비를 마쳤습니다." );
//						System.out.println(c.customerNo + "고객은 " + c.receptionNo + "접수창구와 " + c.repaireNo + "정비창구를 이용했습니다.");
						if(c.receptionNo == A && c.repaireNo == B) ans += c.customerNo;
						repairCounter[i] = null;
						cnt++;
					}
				}
				
				if(cnt == K) break;
				
				// 정비창구 채우기
				for(int i = 1 ; i <= M ; ++i) {
					if(repairCounter[i] == null) {
						if(!repairQueue.isEmpty()) {
							repairCounter[i] = repairQueue.poll();
							repairCounter[i].repaireNo = i;
							repairCounter[i].repairStartTime = time;
//							System.out.println("[" + time + "]" + i + "번 정비창구 " + repairCounter[i].customerNo + "고객이 정비를 시작했습니다." );
						}
					}
				}
				
				time++;
			}
			
			if(ans == 0) ans = -1;
			System.out.println("#" + t + " " + ans);
		}
	}
}
profile
그냥 개발자
post-custom-banner

0개의 댓글