PAT甲题题解-1014. Waiting in Line (30)-模拟,优先级队列

题意:n个窗口,每个窗口可以排m人。有k为顾客需要办理业务,给出了每个客户的办理业务时间。
银行在8点开始服务,如果窗口都排满了,客户就得在黄线外等候。如果有一个窗口用户服务结束,
黄线外的客户就进来一个。如果有多个可选,选窗口id最小的。
输出查询客户的服务结束时间。

如果客户在17点(注意是包括的!!!就在这里被坑了,一开始还以为不包括。。。)或者以后还没开始服务,就输出Sorry
如果已经开始了,无论多长都会继续服务的。

思路:
建立一个优先级队列,存储在黄线之内的所有客户。
对于m*n之前的人,依此往窗口里排队(即优先级队列里)即可。
对于之后的人,从优先级队列里取出结束时间最少的客户,有相同的话则是窗口最小的,
进入他所在的队列。
同时还要建立linetime数组,存储每个窗口排在末尾客户的结束时间。
当窗口j新加进来一个客户,他的起始时间则是linetime[j],结束时间则是linetime[j]+服务时间,同时更新linetime[j]

最后对于查询的客户,如果起始时间>=17:00,则输出Sorry
否则输出对应的结束时间即可,这里方便起见,以分数存储的,所以最后还要转化一下。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=1000+5;
int n,m,k,q;
struct Customer{
    int line;
    int start_time=0;
    int end_time=0;
    int process_time;
    bool operator<(const Customer tmp)const{
        /*
        取队列中最早结束的,如果时间一样,取窗口id最小的
        */
        if(end_time==tmp.end_time)
            return line>tmp.line;
        else
            return end_time>tmp.end_time;
    }
}cus[maxn];
int query[maxn];
int finish_time[maxn];
int main()
{
    scanf("%d %d %d %d",&n,&m,&k,&q);
    for(int i=1;i<=k;i++){
        scanf("%d",&cus[i].process_time);
    }
    for(int i=1;i<=q;i++){
        scanf("%d",&query[i]);
    }
    priority_queue<Customer>queueline;
    int cnt=0;
    Customer tmp;
    int linetime[maxn];
    memset(linetime,0,sizeof(linetime));
    //对于前m*n个人,往队列里插即可
    for(int i=1;i<=m && cnt<k;i++){
        for(int j=0;j<n && cnt<k;j++){
            cnt++;
            tmp.line=j;
            tmp.start_time=linetime[j];
            tmp.end_time=linetime[j]=tmp.start_time+cus[cnt].process_time;
            cus[cnt].line=j;
            cus[cnt].start_time=tmp.start_time;
            cus[cnt].end_time=tmp.end_time;
            queueline.push(tmp);
        }
    }
    Customer c;
    for(int i=cnt+1;i<=k;i++){
        //取出结束时间最早的
        tmp=queueline.top();
        queueline.pop();
        c.line=tmp.line;
        c.start_time=linetime[tmp.line];
        c.end_time=linetime[tmp.line]=c.start_time+cus[i].process_time;
        cus[i].line=c.line;
        cus[i].start_time=c.start_time;
        cus[i].end_time=c.end_time;
        queueline.push(c);
    }
    int cid;
    int maxtime=(17-8)*60;
    for(int i=1;i<=q;i++){
        cid=query[i];
        ///原来开始的时间包括17:00。。。只要是17:00或者是以后的,就不被服务
        ///原来写的是>,结果一部分样例一直没过,还以为自己前面写错了
        if(cus[cid].start_time>=maxtime)
            printf("Sorry\n");
        else{
            int hour=cus[cid].end_time/60;
            int minu=cus[cid].end_time%60;
            printf("%02d:%02d\n",hour+8,minu);
        }
    }
    return 0;
}

时间: 2024-10-18 04:21:16

PAT甲题题解-1014. Waiting in Line (30)-模拟,优先级队列的相关文章

1014. Waiting in Line (30)(模拟题)

Suppose a bank has N windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. The rules for the customers to wait in line are: The space inside the yellow line in front of each window is

PAT甲题题解-1095. Cars on Campus(30)-(map+树状数组,或者模拟)

题意:给出n个车辆进出校园的记录,以及k个时间点,让你回答每个时间点校园内的车辆数,最后输出在校园内停留的总时间最长的车牌号和停留时间,如果不止一个,车牌号按字典序输出. 几个注意点: 1.如果一个车连续多次进入,只取最后一个 2.如果一个车连续多次出去,只取第一个 3.一个车可能出入校园内好几次,停留时间取总和 实际上题目就是让我们求某个时间段内的车辆总和,时间段其实就相当于一个区间,区间求和的话,很快就联想到树状数组和线段树.然而怎么将时间段和区间联系起来呢,那就存储出现在记录和询问里的所有

PAT甲题题解-1119. Pre- and Post-order Traversals (30)-(根据前序、后序求中序)

(先说一句,题目还不错,很值得动手思考并且去实现.) 题意:根据前序遍历和后序遍历建树,输出中序遍历序列,序列可能不唯一,输出其中一个即可. 已知前序遍历和后序遍历序列,是无法确定一棵二叉树的,原因在于如果只有一棵子树可能是左孩子也有可能是右孩子.由于只要输出其中一个方案,所以假定为左孩子即可.下面就是如何根据前序和后序划分出根节点和左右孩子,这里需要定义前序和后序的区间范围,分别为[preL,preR],[postL,postR]. 一开始区间都为[1,n],可以发现前序的第一个和后序的最后一

PAT甲题题解-1109. Group Photo (25)-(模拟拍照排队)

题意:n个人,要拍成k行排队,每行 n/k人,多余的都在最后一排. 从第一排到最后一排个子是逐渐增高的,即后一排最低的个子要>=前一排的所有人 每排排列规则如下: 1.中间m/2+1为该排最高: 2.其他人按各自降序顺序,轮流排到中间最高的左边和右边: 举个例子 190 188 186 175 170 - - 190 - - - 188 190 - - - 188 190 186 - 175 188 190 186 - 175 188 190 186 170 3.当个子一样高时,名字按字典序顺序

PAT甲题题解-1017. Queueing at Bank (25)-模拟

有n个客户和k个窗口,给出n个客户的到达时间和需要的时长有空闲的窗口就去办理,没有的话就需要等待,求客户的平均时长.如果在8点前来的,就需要等到8点.如果17点以后来的,则不会被服务,无需考虑. 按客户的到达时间排序建立一个优先级队列,一开始放入k个窗口,初始结束时间为8*3600然后for循环客户,每次从优先级队列中取出最早结束时间的窗口如果客户比结束时间来的早,就需要等待如果客户比结束时间来的晚,就无需等待最后只要统计那些到达时间在17*3600之前的客户即可. #include <iost

PAT 甲级 1014 Waiting in Line (30 分)(queue的使用,模拟题,有个大坑)

1014 Waiting in Line (30 分) Suppose a bank has N windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. The rules for the customers to wait in line are: The space inside the yellow line

1014. Waiting in Line (30)——PAT (Advanced Level) Practise

题目信息: 1014. Waiting in Line (30) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Suppose a bank has N windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. The rule

PAT甲题题解-1101. Quick Sort (25)-大水题

快速排序有一个特点,就是在排序过程中,我们会从序列找一个pivot,它前面的都小于它,它后面的都大于它.题目给你n个数的序列,让你找出适合这个序列的pivot有多少个并且输出来. 大水题,正循环和倒着循环一次,统计出代码中的minnum和maxnum即可,注意最后一定要输出'\n',不然第三个测试会显示PE,格式错误. #include <iostream> #include <cstdio> #include <algorithm> #include <map&

PAT甲题题解-1108. Finding Average (20)-字符串处理

求给出数的平均数,当然有些是不符合格式的,要输出该数不是合法的. 这里我写了函数来判断是否符合题目要求的数字,有点麻烦. #include <iostream> #include <cstdio> #include <algorithm> #include <string.h> using namespace std; const int maxn=105; bool islegal(char*str){ int len=strlen(str); int p