25行代碼AC——習題5-7 打印隊列(Printer Queue,UVa 12100)——解題報告

勵志用盡量少的代碼做高效的表達。


題目(提交)鏈接→UVa-12100


題目描述:

我們需要用打印機打印任務。每個任務都有1~9間的優先級,優先級越高,任務越急。
打印機的運作方式:從打印隊列裏取出一個任務j,如果隊列裏有比j更急的任務,則直接把j放到打印隊列尾部,否則打印任務j。每次打印都消耗一分鐘的時間,但調整任務位置不消耗時間

輸入:

第一行:n個測試用例
第二行:m1(任務個數) m2(我們關注的任務所在位置)
第三行:m1個任務的優先級。

輸出:

我們關注的任務完成後的時刻。

舉例:

輸入:
1            1個測試用例
4 2            4個任務,我們關注的任務位於4個任務中的第三個(從第0個開始)
1 2 3 4          4個任務的優先級
分析:
1、隊頭任務1是否爲隊列(1,2,3,4)中優先級最高的? 否,移動到隊列末。此時隊列爲:2 3 4 1,時刻爲0
2、隊頭任務2是否爲隊列(2,3,4,1)中優先級最高的? 否,移動到隊列末。此時隊列爲:3 4 1 2,時刻爲0
3、隊頭任務3是否爲隊列(3,4,1,2)中優先級最高的? 否,移動到隊列末。此時隊列爲:4 1 2 3,時刻爲0
4、隊頭任務4是否爲隊列(4,1,2,3)中優先級最高的? 是,打印任務4。此時隊列變爲:1 2 3,時刻從0變爲1
5、隊頭任務1是否爲隊列(1,2,3)中優先級最高的? 否,移動到隊列末。此時隊列爲:2 3 1,時刻爲1
6、隊頭任務2是否爲隊列(2,3,1)中優先級最高的? 否,移動到隊列末。此時隊列爲:3 1 2,時刻爲1
7、隊頭任務3是否爲隊列(3,1,2)中優先級最高的? 是,打印任務3。時刻從1變爲2。
結束判斷,輸出2。


明白了題意,接下來考慮思路:

思路:

最初的思路:
將m1個任務存入隊列,找到隊列中最大的優先級Max。 出隊,若此任務優先級<Max,則入隊(隊尾)。若等於,且不是我們關注的任務:出隊,T++。
若等於,且是我們關注的任務,T++,輸出T。結束循環。
在實施操作中發現了以下幾個難點:
難點1:如何判斷打印的任務是我們關注的任務?
解決辦法:將每個優先級都+10000,若爲標記任務的優先級,加20000。優先級間相互判斷前做一下取餘。如:10005%10000 = 20005%10000。這種方法叫做自定義標記法。
難點2:最初的想法是在輸入時用Max變量存儲優先級最高的任務, 但如果該任務被打印,Max變動,該怎樣找到當前隊列中優先級最高的任務?
解決辦法:降序優先隊列(priority_queue<int>Max)存儲優先級,每當優先級最高任務被打印,就出隊一次。
最終的思路:
將m1個任務的優先級做標記後存入隊列q(queue<int>q),將不做標記的優先級存入降序優先隊列Max(priority_queue<int>Max)。q出隊,若優先級%10000<Max.top(),則入隊(隊尾), 若優先級%10000=Max.top(),且<20000,q出隊,Max出隊,T++; 若>20000,則輸出T,結束循環。

代碼:

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n;  cin >> n; while(n--) {
		int m1, m2; cin >> m1 >> m2;			//任務數和關注的任務所在位置
		int T = 0;								//隊列中最大的優先級、時刻 
		queue<int>q;							//主隊列 
		priority_queue<int>Max;					//降序優先隊列,存儲優先級 
		for(int i = 0; i < m1; i++)  { 
			int x; cin>>x; 
			Max.push(x);						//壓入優先級(Max 中是原本優先級的數)
			i == m2 ? x+=20000 : x+= 10000;		//將關注任務的優先級做標記 
			q.push(x); 							//任務入隊 
		}
		while(1) {
			int x = q.front(); 
			q.pop();
			if((x%10000) < Max.top()) { q.push(x); }						//若不是當前最高優先級,則回隊尾 
			else 	
				if(x >= 20000) { T++; cout << T << endl; break;}			//若是,且爲關注的任務,則輸出,結束循環。 
				else { Max.pop(); T++; }									//若不是關注的任務,則T++, Max出隊,q出隊,T++ 		
		}
	} 
	return 0;
} 

收穫:

1、才知道隊列是沒有迭代器的。(不要笑話我o(╯□╰)o)
2、自定義標記法做標記


擇苦而安,擇做而樂,虛擬現實終究比不過真實精彩之萬一。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章