Study/Baekjoon

Baekjoon1966: 프린터 큐 , 다양한 풀이

devyoseph 2021. 10. 23. 22:05

문제

여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에 쌓여서 FIFO - First In First Out - 에 따라 인쇄가 되게 된다. 하지만 상근이는 새로운 프린터기 내부 소프트웨어를 개발하였는데, 이 프린터기는 다음과 같은 조건에 따라 인쇄를 하게 된다.

  1. 현재 Queue의 가장 앞에 있는 문서의 ‘중요도’를 확인한다.
  2. 나머지 문서들 중 현재 문서보다 중요도가 높은 문서가 하나라도 있다면, 이 문서를 인쇄하지 않고 Queue의 가장 뒤에 재배치 한다. 그렇지 않다면 바로 인쇄를 한다.

예를 들어 Queue에 4개의 문서(A B C D)가 있고, 중요도가 2 1 4 3 라면 C를 인쇄하고, 다음으로 D를 인쇄하고 A, B를 인쇄하게 된다.

여러분이 할 일은, 현재 Queue에 있는 문서의 수와 중요도가 주어졌을 때, 어떤 한 문서가 몇 번째로 인쇄되는지 알아내는 것이다. 예를 들어 위의 예에서 C문서는 1번째로, A문서는 3번째로 인쇄되게 된다.

입력

첫 줄에 테스트케이스의 수가 주어진다. 각 테스트케이스는 두 줄로 이루어져 있다.

테스트케이스의 첫 번째 줄에는 문서의 개수 N(1 ≤ N ≤ 100)과, 몇 번째로 인쇄되었는지 궁금한 문서가 현재 Queue에서 몇 번째에 놓여 있는지를 나타내는 정수 M(0 ≤ M < N)이 주어진다. 이때 맨 왼쪽은 0번째라고 하자. 두 번째 줄에는 N개 문서의 중요도가 차례대로 주어진다. 중요도는 1 이상 9 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.

출력

각 테스트 케이스에 대해 문서가 몇 번째로 인쇄되는지 출력한다.

 

풀이

입력이 좀 난해한 것 같다. 풀어서 정리해보았다.

시행횟수 T 를 제외하고 다음의 반복이다

문서의 수 N 궁금한 문서 M
중요도 나열(N개)

현재 문서도와 나머지 문서들의 중요도를 비교해야하는데 큐만 이용해서는 중요도를 비교할 수 없을 것이다.

스택에서와 같이 순서의 기록은 배열 안에서 해주어야 한다. 메모리 제한이 있기에 배열만 사용한다(2개).

특이한 점은 문서의 번호가 0번부터 시작한다는 것이다.

 

1) 0부터 N-1까지 문서에 해당하는 중요도를 넣어준다

2) 크기가 10인 배열을 만들고 중요도가 n인 문서를 만날 때마다 배열의 n index에 1을 더한다

3) 문서 내에서 현존 최대 중요도를 max값에 저장한다

→ 9번 index부터 값이 0이 될 때마다 max값이 왼쪽으로 이동하도록 한다

4) max값과 같은 값이면 값을 꺼내고 중요도를 0으로 만든다, 다른 값이면 지나간다

 

2개의 큐

import java.util.*;

class Data{
	int idx;
	int prior;
	Data(int idx,int prior){
		this.idx = idx;
		this.prior = prior;
	}
}
public class Main {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    Queue<Data> queue = new LinkedList<Data>();
    Queue<Integer> queue2 = new LinkedList<Integer>();
    int t = sc.nextInt();
    while(t-->0) {
    	int N = sc.nextInt(); //총 개수
    	int M = sc.nextInt(); //궁금한 인덱스
    	int cnt = 0;
    	int counting[] = new int[10];
    	for(int i=0; i<N;i++) {
    		int now = sc.nextInt();
    		queue.offer(new Data(i,now));
    		counting[now]++;
    	}
    	for(int i=9; i>0;i--) {
    		for(int j=0; j<counting[i]; j++) {
    			queue2.offer(i);
    		}
    	}
    	while(true) {
    		if(queue.peek().prior==queue2.peek()) {
        		cnt++;
    			if(queue.poll().idx==M) {
    				break;
    			}else {
    				queue2.poll();
    			}
    		}else {
    			queue.offer(queue.poll());
    		}
    	}
    	System.out.println(cnt);
    	queue.clear();
    	queue2.clear();
    }
}
}

 

2개의 배열

import java.io.*;
import java.util.StringTokenizer;
public class Main {
	static int max;
public static void main(String[] args) throws IOException{
	 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	 StringTokenizer st;
	 int T = Integer.parseInt(br.readLine());
	 while(T--> 0) {
		 st = new StringTokenizer(br.readLine()," ");
		 int N = Integer.parseInt(st.nextToken());
		 int M = Integer.parseInt(st.nextToken());
         
		 int[] priority = new int[10];
         //중요도 배열, 3index에는 중요도 3에 해당하는 문서의 개수
		 
         int[] document = new int[N]; //각 문서들의 중요도가 들어간다
         
		 int count =0; //현재까지 문서를 출력한 개수
		 int out =-1; //문서를 출력할 때 out을 통해 현재 출력하는 문서의 번호를 기억
         
		 int now=0; //while문을 사용하기에 현재 index번호를 계속 돌려줄 now를 지정
         
		 st = new StringTokenizer(br.readLine()," ");
		 
         for(int i=0; i<N; i++) {
			 int num = Integer.parseInt(st.nextToken());
			 priority[num]++; //문서들의 중요도 분류
			 document[i] = num;
		 }
         
		 findMax(priority); //중요도의 최대값을 찾는다
		 
         while(out!=M) {
			 if(document[now]==max) { //최대값과 같은 값만 출력
				 out = now;
				 document[now]=0; //출력한 문서는 중요도 0으로 바꿈
				 count++;
				 priority[max]--;
				 findMax(priority);
			 } 
			 now++;
			 if(now==N) { //now가 배열에 끝에 다다를 때마다 처음으로 위치를 돌려준다
				 now=0;
			 }
		 }
		bw.write(count+"\n");
	 }
	 bw.flush();
	 bw.close();
}
public static void findMax(int[] priority) {
	for(int i=9; i>=1; i--) {  
		if(priority[i]!=0) {
			max = i;
			i=0;
		}}
	//중요도 9부터 0이 아닌 값을 발견한 순간 max로 갱신하고 반복문을 닫는다
}
}

*코드 길이는 조금 길지만 메모리 사용이 나쁘지 않다

 

배열 1개 큐 1개

import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
	static int max;
public static void main(String[] args) throws IOException{
	 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	 StringTokenizer st;
	 Queue<Integer> queue = new LinkedList<>();
	 int T = Integer.parseInt(br.readLine());
	 while(T--> 0) {
		 st = new StringTokenizer(br.readLine()," ");
		 int N = Integer.parseInt(st.nextToken());
		 int M = Integer.parseInt(st.nextToken());
		 int[] document = new int[N];
		 int count =0;
		 int out =-1;
		 int now=0;
		 st = new StringTokenizer(br.readLine()," ");
         
		 for(int i=0; i<N; i++) {
			 queue.offer(i);  //큐에 0부터 N-1까지 집어넣는다
			 document[i] = Integer.parseInt(st.nextToken()); //배열에 중요도를 입력
		 }
         
		 while(out!=M) { //출력되는 문서가 M과 같아지는 순간 반복문을 나온다
			 boolean ismax = true;
             
			 now = queue.peek(); //현재 큐의 꼭대기값을 가져온다
             
			 for(int i=0; i<N; i++) {
				 if(document[now]<document[i]) ismax=false; //하나라도 큰게 있으면 false
			 }
			 if(ismax) { //true일 경우 문서를 뽑아낸다. 배열에서 중요도를 0으로 만들고 count해준다
				 document[now] =0;
				 out=queue.poll();
				 count++;
				 }
			 else queue.offer(queue.poll());
			}
		 queue.clear(); //queue의 초기화
		bw.write(count+"\n");
	 }
	 bw.flush();
	 bw.close();
}}

 

Scanner (숏코딩)

import java.util.*;
public class Main {
	static int max;
public static void main(String[] args) {
	 Scanner sc = new Scanner(System.in);
	 int T = sc.nextInt();
	 for(int i=0;i<T;i++) {
		 int N = sc.nextInt();
		 int M = sc.nextInt();
		 Queue<Integer> queue = new LinkedList<>();
		 int[] doc = new int[N];
		 int count =0;
		 int out =-1;
		 for(int j=0; j<N; j++) {
			 queue.offer(j);
			 doc[j] = sc.nextInt();}
		 while(out!=M){
			 boolean ismax = true;
			 int now = queue.peek();
			 for(int j=0; j<N; j++){if(doc[now]<doc[j]) ismax=false;}
			 if(ismax) {doc[now] =0;out=queue.poll();count++;}
			 else queue.offer(queue.poll());}
		System.out.println(count);}}}

*메모리 사용이 늘었다

'Study > Baekjoon' 카테고리의 다른 글

Baekjoon1021: 회전하는 큐, 덱의 배열화  (0) 2021.10.24
Baekjoon10866: 덱  (0) 2021.10.24
Baekjoon11866: 요세푸스 문제 0  (0) 2021.10.23
Baekjoon2164: 카드2  (0) 2021.10.23
Baekjoon18258: 큐 2  (0) 2021.10.22