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、自定义标记法做标记


择苦而安,择做而乐,虚拟现实终究比不过真实精彩之万一。

发布了84 篇原创文章 · 获赞 78 · 访问量 9265

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/104797219