[標準C++]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行で構成されています.
テストケースの最初の行には、ドキュメントの数N(1≦N≦100)と、現在のQueueで何位にランクされているかを示す整数M(0≦M

しゅつりょく


各テスト例について、ドキュメントの数回目の印刷を出力します.
https://www.acmicpc.net/problem/1966
優先順位を用いた簡単な解答もあり,筆者は問題で説明したように体現した.
まず、ベクトルのすべての入力値(受信時に周波数配列で各重要度をチェックする周波数)を受け入れ、検索するドキュメントの位置(findIndex=M)と現在のドキュメントの位置(currentIndex=0)を定義します.
繰り返した文を無限に回して
毎回currentIndex++;
ベクトル(list)の0番目のドキュメントを確認します.
この文書の重要度は大きく9と9に分けられます.
9でない場合は、現在のドキュメントよりも重要度の高い重要度のドキュメントがあるかどうかという2つのケースに大別されます.
もちろん、重要度が大きい場合は、ベクトル(list)0を保存し、ベクトルから削除し、ベクトルの最後に再追加します.
つまり.

  • 現在のドキュメントの重要度は9未満ですか?(true)
    1-1. 現在のドキュメントよりも重要なドキュメントはありますか?
    true:list[0]からベクトルの最後まで
    -現在のドキュメントが検索するドキュメントの場所にある場合は、繰り返し終了します.(最終res出力)
    false:現在のドキュメントを印刷します.(res++;)
    -現在のドキュメントが検索するドキュメントの場所にある場合、
    findIndex= list.size()-1 , currentIndex = 0; すべての場所をリセットしてリフレッシュ

  • 現在のドキュメントの重要性が9の場合(1条件のfalse)
    2-1. 現在のドキュメントが検索するドキュメントの場所にある場合は、
    現在のドキュメントを出力した後、重複文を終了します(res++;)
    2-2. 現在のドキュメントが検索するドキュメントの場所でない場合.
    現在はドキュメントのみ出力されています.(res++;)
  • 実際には、現在のドキュメントの重要性を各号のlist[0]と分類する必要はなく、コードを記述する必要もありません.
    地域分けをより明確にするために分類した.(ドアが9番の時は小さいけど…)
    コード全体を以下に示します.
    #define _CRT_SECURE_NO_WARNINGS
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(void) {
    	int t;
    	scanf("%d", &t);
    	while (t--) {
    		int N, M;
    		vector<int> list;
    		scanf("%d%d", &N, &M);
    		//벡터에넣고 벡터 사이즈를 매번 갱신
    		//원하는 데이터가 나올때까지 전부 구현함
    		int frequency[10] = {}; //빈도수 체크
    		for (int i = 0, temp; i < N; i++) { 
    			scanf("%d", &temp);
    			list.push_back(temp);
    			frequency[temp]++;
    		}
    		int findIndex = M; //찾고자하는 문서위치
    		int currentIndex = 0; //현재 문서 위치
    		int res = 0; //출력횟수
    		//printf("&&& 찾문:%d  ", findIndex);
    		while (true) {
    			int currentPriority = list[0]; //현재문서의 중요도
    			if (currentPriority != 9) { //현재문서가 중요도9가 아닌경우
    				bool cantPrint = false;
    				//찾는문서보다 높은 중요도의 문서들이 있는지 확인
    				for (int i = 9; i >= currentPriority + 1 ; i--) {
    					if (frequency[i]) {
    						cantPrint = true;
    						break;
    					}
    				}
    				//찾는문서의 위치가아니고
    				if (cantPrint) { //더높은 중요도의 문서가 있는경우
    					int temp = list[0];
    					//맨뒤로 옮김
    					list.erase(list.begin() + 0); 
    					list.push_back(temp);
    					//찾는문서의 위치였다면
    					if (currentIndex == findIndex) {
    						//찾는 문서위치 갱신
    						findIndex = list.size() - 1;
    						//현재 문서위치 갱신
    						currentIndex = 0;
    						continue;
    					}
    				}//찾는문서의 위치가아니고
    				else { //더높은 중요도의 문서가 없는 경우
    					//출력
    					list.erase(list.begin() + 0); //현재 문서 삭제
    					frequency[currentPriority]--; //현재 문서 빈도수 -1
    					res++; //출력함
    					//찾는문서의 위치였다면
    					if (currentIndex == findIndex) break;
    				}
    			}
    			else { //현재 문서 중요도가 9인경우 바로 출력가능
    				//찾는문서의 위치이면
    				if (currentIndex == findIndex) {
    					res++;
    					break; //계산끝
    				}
    				else {
    					//출력
    					list.erase(list.begin() + 0); //현재 문서 삭제
    					frequency[currentPriority]--; //현재 문서 빈도수 -1
    					res++; //출력함
    				}
    			}
    			currentIndex++; //현재문서위치를 다음으로
    		}
    		printf("%d\n", res);
    	}
    }