【题意解析】
有一个打印工作的队列,每个工作有一个优先级(范围0~9),数值越大,优先级越高。打印顺序要按照优先级由高到低,因此如果队列头的工作的优先级不是整个队列中最大的,那么就必须回到队列尾继续等待。如果队列头的工作优先级是最高的,那么就执行这个打印工作,并将其从队列中删除。
给定队列的长度和你的工作所在的位置(位置标号从队列头开始为0、1、2、3...n-1),要求出完成你的打印工作所需要的时间(包括打印你自己的那个时间)。注意,打印一个工作的时间为1,从队列头移到队列尾不计时间。
【思路提示】
方法1:直接使用queue来模拟这个过程。
我的实现:
使用priority_queue维护整个队列的优先级信息,每次可以直接取出最大的优先级。用一个数组存放初始的队列,数组值为每个位置的优先级。用数组下标index来记录队列头的位置,将队列头移到队列尾的操作转换为下标的移动。当下标所指的工作可以被打印,则将其优先级改为-1(比最小优先级小),时间加1,从优先队列中删除这个最大的优先级(也即删除priority_queue的队列头)。结束条件为当前工作的优先级最大,且下标index等于你的工作所在的位置m。
【代码】
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int main(){
int n, m, t, hightest, index, time;
int priority[101];
cin >> t;
while (t--){
cin >> n >> m;
for (int i = 0; i < n; ++i)
cin >> priority[i];
int my_pri = priority[m];
priority_queue<int> pq(priority, priority+n);
index = 0;
time = 0;
hightest = pq.top();
while (my_pri < hightest || index != m){
if (hightest <= priority[index]){
time++;
priority[index] = 0-1;
pq.pop();
hightest = pq.top();
}
index++;
if (index >= n)
index = 0;
}
cout << time+1 << endl;
}
return 0;
}
【疑问】
起初,我采用的是用另外一个数组printed[101]来记录一个工作是否被打印,而不是采用修改已经打印的工作的优先级。为了能够再优化一点点,我在循环体末尾增加循环判断,如果下标所指的工作已经打印,就继续移动下标而不是进入下一次循环。试了好几个测例都没错,但是就是WA,不知是哪里出问题了。有知道的欢迎指教。
while (my_pri < hightest || index != m){
if (hightest <= priority[index]){
time++;
printed[index] = 1;
pq.pop();
hightest = pq.top();
}
index++;
while (printed[index] == 1)
index++;
if (index >= n)
index = 0;
}