[Baekjoon]1966号(SILVErIII):プリンタキュー(Java)


1. Problem 📃
[プリンタキュー]
https://www.acmicpc.net/problem/1966
[質問]
ご存じのように、プリンタでは、印刷するドキュメントを印刷コマンドを受信した順序、すなわち、要求されたドキュメントを先に印刷します.複数の文書がキュー資料構造に積み重ねられている場合、FIFO-Firstの第1の出力に従って印刷されます.しかし、尚根は、以下の条件で印刷する新しいプリンタ内部ソフトウェアを開発した.
  • 現在のQueueの一番前の文書の「重要度」を確認します.
  • の残りのドキュメントに現在のドキュメントよりも重要なドキュメントがある場合は、そのドキュメントを印刷せずにQueueの一番後ろに再配置します.さもないとすぐに印刷します.
  • 例えばQueueには4つの文書(A B C D)があり、重要度が2 1 4 3であればCを印刷し、DとA、Bを印刷する.
    現在のキュー内のドキュメントの数と重要性を指定したときに、どのドキュメントが何回目に印刷されたかを特定します.例えば、上記の例では、Cドキュメントが1位、Aドキュメントが3位となっている.
    2. Input 📇
    [入力]
    最初の行は、テスト・インスタンスの数を示します.各テストボックスは2行で構成されています.
    テストケースの最初の行には、ドキュメントの数N(1≦N≦100)と、現在のQueueで何位にランクされているかを示す整数M(0≦M3. Output 📠
    [出力]
    各テスト例について、ドキュメントの数回目の印刷を出力します.
    4. Example 📚
    [IO例]
    例入力例出力3105421 2 3 4601 1 9 1125
    5. Solution 🔑
    この問題で、キューに並んでいることを初めて知りました.
  • テストケースを入力する変数(T)を宣言し、テストケース(T)と繰り返し入力します.
  • 試験例はint型配列の「リンクリスト」(LinkedList)を宣言する.
    計算する変数(count)を0に初期化し、数回目の出力を宣言します.
    ジョブの個数(N)と、ジョブの中で何番目にあるかの通知(M)を入力します.
  • LinkedList(q)にワークロードが含まれている場合、含まれる順序と優先度が2つの1次元配列を作成し、
    0番目のインデックスには、最初のワークベンチの場所が含まれ、1番目のインデックスには優先度が含まれます.
  • Qの許しを請うまで、ループを返していました.
    まず、一番前のキュー値(front)を格納し、一番前の値が最も優先度が高いと仮定するブール変数を設定します.
    キュー内で最大値をリアルタイムで検索する変数(highVal)と、その値インデックスを含む変数(high)を宣言します.
  • キューでは、qからインポートされた配列の優先度[1]がfront[1]より大きい場合、最大と考えられるブール変数がfalse値に変更され、qからインポートされた配列の優先度[1]の値がリアルタイムで変更されたhighVal[1]の値より大きい場合、それが最大値に変更され、何番目の高変数に格納される.
  • 最大値
  • でない場合、最大優先度を持つ場所より前のすべての値が戻され、最も前の値がポーリングされ、count値が上昇しながらキューから削除されます.ポーリングの前に、先頭値の0番目のインデックス、すなわち、キュー内の最初の位置[0]の値が上に表示されたM値と同じであることを示す場合、この操作を優先的に処理する必要があるため、count値を増やして無限ループを終了し、各テストケースのStringBuilder()にcount値を追加する必要がある.
  • 最終的なStringBuilder()値
  • を出力します.
  • 6. Code 💻
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.StringTokenizer;
    
    public class Main {
    
    	public static void main(String[] args) throws IOException {
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		StringBuilder sb = new StringBuilder();
    		
    		int T = Integer.parseInt(br.readLine());
    		
    		for(int i=0; i<T; i++) {
    			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
    			
    			LinkedList<int[]> q = new LinkedList<int[]>();
    			
    			int count = 0;
    			
    			int N = Integer.parseInt(st.nextToken());
    			int M = Integer.parseInt(st.nextToken());
    			
    			st = new StringTokenizer(br.readLine(), " ");
    			
    			for(int j=0; j<N; j++) {
    				q.offer(new int[] { j, Integer.parseInt(st.nextToken()) } );
    			}
    		
    			while(!q.isEmpty()) {
    				
    				// 가장 맨 앞 값을 저장함.
    				int[] front = q.peek(); //{q.peek()[0], q.peek()[1]};
    //				System.out.println(Arrays.toString(front));
    				// 가장 크다는 가정을 시킴. 
    				boolean Max = true;
    				// 혹시나 제일 큰 값이 있다면 몇 번째 있는지.
    				int[] highVal = q.peek();
    				int high = 0;
    				
    				// 큐를 확인하면서 본인보다 큰 값이 있다면
    				// Max를 false로 변경 후 가장 큰 값의 위치를 선정.
    				for(int k=0; k<q.size(); k++) {
    					
    					if(q.get(k)[1] > front[1]) {
    						Max = false;
    						if(highVal[1] < q.get(k)[1]) {
    							highVal = q.get(k);
    							high = k;
    						}
    					}
    				}
    				// 가장 큰 값이 아니였다면, 앞의 값들을 모두 뒤로 offer.
    				if(Max == false) {
    					for(int j=0; j<high; j++) {
    						q.offer(q.poll());
    					}
    				}
    				// 뽑을 값의 인덱스가 초기 위치에 있던 값이랑 같다면
    				// 개수를 증가시키고 종료하고 다음 케이스를 받을 준비.
    				if(q.peek()[0] == M) {
    					count++;
    					break;
    				}
    				
    				// 같지 않다면 그냥 뽑고 count값을 증가시킴.
    				q.poll();
    				count++;
    			}
    			sb.append(count).append("\n");
    		}
    		System.out.println(sb);
    	}
    
    }
    
    7. Growth 🍄
    その間にQueueまたはStackを作成し,LinkedListで表現できることを知った.
    また,配列を用いてキューに配列形式の値を入れることも可能であることが分かった.
    Q[0]Q[1]Q[2]Q[3][0, 2][1, 4][2, 3][3, 1]
    このように置くことができます