Uva12100Printer Queue NWERC2008 解题报告

该博客详细介绍了ACM竞赛题目UVA12100 Printer Queue的解题报告。根据题意,任务遵循先进先出原则,适合使用队列数据结构解决。博主通过创建结构体包装位置和优先级,利用队列的移动和检查函数实现题目要求。在输入任务时记录优先级并排序,通过比较当前最大优先级与队首元素的优先级来决定是否打印。满足特定条件时,操作结束。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

学生会里只有一台打印机,但是有很多文件需要打印,因此打印任务不可避免地需要等待。有些打印任务比较急,有些不那么急,所以每个任务都有一个1~9件的优先级,优先级越高表示任务越急。
打印机的运作方式如下:首先从打印队列里取出一个J,如果队列里有比J更急的任务,则直接把J放到打印队列尾部,否则打印任务J(此时不会把它放回打印队列)。
即每次都只打印队列中最大优先级的任务
输入打印队列中各个任务的优先级以及所关注的任务在队列中的位置(位置从0开始计数)。输出该任务完成的时刻。所有任务都需要1分钟打印,移动任务不耗费时间。
测试数据:
3    //3个样例
1 0  //任务数 , 所关注任务在队列中的位置
5    //对应每个任务的优先级
4 2
1 2 3
6 0
1 1 9 1 1 1

输出

1
2
5

运行方式例如第二组测试数据

1 2 3 4
2 3 4 1
3 4 1 2
4 2 1 3
打印4
2 1 3
1 3 2
3 2 1
打印3,结束

题解

任务符合先进先出,所以很容易想到用queue类型的数据结构来解决此题。
①首先先抽象出两个关键的要素:位置,优先值
②移动的方式:void move()函数
③判断输出是否符合要求:bool check() (关键)
如何具体实现这三个步骤:
①用struct包装
②先查看队首元素,如果符合要求直接输出,否则将其出队并放到队尾
③在刚开始输入任务对应的优先级时把优先级用一个数组记录下来,并将其按照从大到小排序,设定一个指针ptr总是指着当前队列中最大的优先级。当查看队首元素时,如果优先级符合当前的最大优先级即可进行打印,并且将ptr往后移动(指向下一个最大的优先级),若不符合,则进行move操作。
当且仅当满足check()条件并且满足所关注任务的位置时,操作结束。

具体代码:

#include <set>
#include <numeric>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <functional>

using namespace std;

typedef long long LL;

#define REP(idx1,num1) for(int idx1=0;idx1<(num1);idx1++)
#define pb push_back
#define empb emplace_back
#define mp make_pair
//上面是一些个人习惯
const int maxn = 100+10;
struct node{
    int pos;//位置
    int pt;//优先级
    node(int pos = -1,int pt = -1):pos(pos),pt(pt){}//构造函数
};
bool cmp(int a,int b)
{
    return a>b;
}
queue <node> q;
int str_pt[maxn];//优先级
int t = 0;
int max_pt;//当前最大优先级
int ptr = 0;//str_pt的指针
int sum_j;int you_pos;//任务数,所关注任务的位置


void move()
{
    node tmp = q.front();
    q.pop();
    q.push(tmp);
}
inline bool check()
{
    node tmp = q.front();
    if(tmp.pt == max_pt)//满足当前最大优先级
    {
        q.pop();
        t++;
        ptr++;//移动到下一个最大优先级
        if(tmp.pos == you_pos)//是我所关注的那个任务呢
            return true;
    }
    else
        move();
    return false;
}
void clear(queue<node>& q) //清空队列
{
    queue<node> empty;
    swap(empty, q);
}
int main()
{
    int T;
    cin >> T;
    while(T--){
        t = 0;ptr = 0;
        cin >> sum_j >> you_pos;
        int j = 0;
        REP(i,sum_j){//从 i = 0, i < sum_j; i++
            int pt;
            cin >> pt;
            node n = node(i,pt);
            q.push(n);
            str_pt[j++] = pt;
        }
        sort(str_pt,str_pt+j,cmp);//从大到小排序
        bool flag = false;
        while(!flag){
            max_pt = str_pt[ptr];
            if(check())
                flag = true;
        }
        cout << t << endl;
        clear(q);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值