백준 17225 - 세훈이의 선물가게

Updated:

Java

17225 번 - 세훈이의 선물가게

문제

세훈이는 선물가게를 운영한다. 세훈이의 선물가게는 특이하게도 손님이 어떤 선물을 구매할지 선택할 수가 없다. 대신 세훈이의 취향으로 랜덤하게 준비된 선물 중 몇 개를 구매할 것인지, 파란색과 빨간색 중 어떤 색으로 포장 받을 것인지만 결정해 주문할 수 있다.

상민이와 지수는 세훈이의 가게에서 선물 포장을 맡은 아르바이트생이다. 손님들은 파란색 포장지를 원하면 상민이에게, 빨간색 포장지를 원하면 지수에게 주문을 한다. 두 사람은 각자 주문을 받으면 그때부터 포장을 시작하는데, 현재 남아있는 선물 중 가장 앞에 있는 선물을 가져와 포장하고 주문을 받은 개수만큼 이를 반복하는 형태다. 이때 선물 하나를 포장하는 데 상민이는 A초, 지수는 B초가 걸린다. 두 사람 모두 받거나 밀린 주문이 없는데 미리 선물을 가져오거나 포장하는 일은 없으며, 두 사람이 동시에 선물을 가져올 때는 알바짬이 조금 더 있는 상민이가 먼저 가져오고, 지수가 그 뒤의 선물을 가져온다.

세훈이는 어제 구매한 선물이 망가져 있다는 항의 전화를 받았다. 자신이 준비한 선물에는 문제가 없었기에 손님에게 포장지의 색을 물었지만, 손님은 자신이 받은 선물이 무엇인지만 말하며 화를 낼 뿐이었다. 어쩔 수 없이 세훈이는 어제 가게를 방문한 손님들의 주문 내역을 보고 그 선물을 누가 포장했는지 파악하려 한다.

방문한 손님의 수와 각 손님이 주문한 시각, 선택한 포장지, 포장 받을 선물의 개수가 주어졌을 때 상민이와 지수가 각자 어떤 선물들을 포장했는지 알아내는 프로그램을 작성해보자.

문제 출처

접근 방법

문제에서 요구하는 것은 상민이와 지수가 포장한 선물들에 순서를 부여하는 것이다.

  1. 상민이와 지수가 각 선물을 포장할 때의 시작 시간을 기록한다.
  2. 앞서 기록한 각 선물의 포장 시간을 확인하며 순서를 부여한다.
  3. 상민이와 지수가 포장한 선물의 개수와 시간을 출력한다.

구현

상민(B)와 지수(R)가 각 선물을 포장하는 시작 시간을 담는 Queue를 2개 생성한다.
손님의 주문 시간에서 부터 m개 까지 포장 하는데 걸리는 시간 A, B의 간격에 따라 위 queue에 저장한다.
예를 들어, 상민이의 포장 시간이 2초이고, 1초에 3개의 선물을 주문 했으면, 상민의 Queue에 [1, 3, 5]를 저장한다.
만약 다음 손님이 또 상민이에게 6초에 2개를 주문하는 상황이 오면, 상민은 7초에 포장이 끝나므로, 7초부터 포장을 시작하여 [1, 3, 5, 7 ,9]가 된다.

위 과정을 반복하면, 다음과 같이 상민 / 지수의 queue에 선물 포장 시작 시간이 다 저장되어 있다.

상민 : [1, 3, 5, 7, 9]  
지수 : [4, 7, 12]  

이제 위 선물들의 순서를 부여해야 하며, 이는 while문을 통해 시간을 증가 시키며 queue에 현재 시간에 맞는 선물이 있으면, pop을 하며 순서를 부여한다.
첫 번째 예제와 같이 포장 시간이 0초인 [1, 1, 1] 상황을 방지하기 위해 peek으로 한번 더 확인한다.

코드

/*
17225번 - 세훈이의 선물가게
https://www.acmicpc.net/problem/17225
*/

import java.util.*;
import java.io.*;

public class Main {
	
    public static void main(String []args) throws IOException {        
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer stk = new StringTokenizer(br.readLine());
    	int bS = stoi(stk.nextToken());
    	int rS = stoi(stk.nextToken());			
    	int csNum = stoi(stk.nextToken());		// customer number
    	
    	int time, pNum, bTime = 0, rTime = 0;	// 왼쪽부터 손님이 주문하는 시간, 물건의 개수 , 상민의 포장이 끝날때 까지 걸리는 시간, 지수의 포장이 끝날 때 까지 걸리는 시간
    	char color;
    	Queue<Integer> bp = new LinkedList<Integer>();
    	Queue<Integer> rp = new LinkedList<Integer>();
		// 주문 및 포장
    	while(csNum-- != 0) {
    		stk = new StringTokenizer(br.readLine());
    		time = stoi(stk.nextToken());
    		color = stk.nextToken().charAt(0);
    		pNum = stoi(stk.nextToken());
    		
    		if(color == 'B') {			// 상민이의 경우
	    		if(time < bTime)		// 만약 손님을 받은 시간에 아직까지 포장을 하고 있으면 포장이 끝나는 시간으로 변경 해준다.
	    			time = bTime;
	    		
	    		for(int i = 0; i < pNum; i++) {		// 주문한 선물의 개수만큼 반복
	    			bp.offer(time);					// 포장 시작
	    			time += bS;						// 포장 시간 간격으로 증가
	    			bTime = time;					// 마지막 포장이 끝나는 시간
	    		}
    		}
    		else {						// 지수의 경우, 상민과 동일
    			if(time < rTime)
	    			time = rTime;
	    		
	    		for(int i = 0; i < pNum; i++) {
	    			rp.offer(time);
	    			time += rS;
	    			rTime = time;
	    		}
    		}
    	}
		// 포장 끝, 포장한 선물들의 번호 부여
    	int curT = 0, idx = 1;				// curT는 시간, idx는 선물의 번호
    	ArrayList<Integer> ba = new ArrayList<>();	
    	ArrayList<Integer> ra = new ArrayList<>();
    	while(!bp.isEmpty() || !rp.isEmpty()) {	
    		if(!bp.isEmpty() && curT == bp.peek()) {	// 현재 시간에 상민이 포장을 했으면.
    			ba.add(idx++);
    			bp.poll();
    			if(!bp.isEmpty() && curT == bp.peek())	// 현재 시간에 상민이 또 포장을 했으면,
    				continue;
    		}
    		if(!rp.isEmpty() && curT == rp.peek()) {
    			ra.add(idx++);
    			rp.poll();
    			if(!rp.isEmpty() && curT == rp.peek())
    				continue;
    		}
    			
    		curT++;		// 시간이 증가한다.
    	}
    	
		// 상민이가 포장한 선물의 개수, 번호 / 지수가 포장한 선물의 개수, 번호
    	System.out.println(ba.size());
    	for(int v : ba)
    		System.out.print(v + " ");
    	System.out.println();
    	System.out.println(ra.size());
    	for(int v : ra)
    		System.out.print(v + " ");
    	
    	br.close();
    }
    static int stoi(String str) {
    	return Integer.parseInt(str);
    }

}

총평

난이도

⭐⭐★★★

후기

Queue를 이용하면 쉽게 해결 할 수 있는 문제.

개선할 점