题目链接:https://www.patest.cn/contests/pat-a-practise/1014
题目大意:银行有N个窗口,每个窗口前的黄线内最多排队M个人,有K个人要去办理业务,每个人要办理的时间已知。排队的规则跟现实生活中的排队类似,黄线内没有位置的时候,在线外候着;黄线内有位置的时候,选择队列最短的去排队,若有两个队长度相同,则选择队列序号小的排入。最后计算每个人办理完结束的时间。
解题思路:
每个人用结构体表示,分量有要接受服务的时间serve;离开的时间leave,为便于计算,用分钟表示,最后再进行转换.
N个窗口,用N个队列来表示.
customer[i].leave=open[windowindex]+customer[i].serve.其中open[windowindex],windowindex表示该人所在窗口的序号;open[windowindex]为该人开始办理时的时间,该时间又等于上一个离开的时间,即当前人的open[windowindex]=customer[i-1].leave;下一个人的open[windowindex]=cusomer[i].leave
确定每个人应该选择哪个窗口时有两种情况:
1.黄线内的部分:每个人的窗口号为p%N
2.黄线的外的人比较复杂。判断黄线外的人的窗口好的时候,选择所有队列中队头的人离开时间最早的那个队排入
代码如下:
#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
using namespace std;
struct person
{
int serve,leave;//要接受服务的时间,离开的时间
};
int main(int argc, char const *argv[])
{
int N,M,K,Q;
cin>>N>>M>>K>>Q;
person curstomers[K];//共k个人
/*输入每个人接受服务的时间*/
for(int i=0;i<K;i++)
cin>>curstomers[i].serve;
vector<queue<int>> window(N);//共N个窗口
int open[N]={0};//每个窗空闲出来的时间初试化为0
/**先把黄线内的人离开时间确定下来**/
int p;//
for(p=0;p<M*N&&p<K;p++){
curstomers[p].leave=open[p%N]+curstomers[p].serve;//该顾客结束的时间为当前窗口空闲出的时间+需要服务的时间
open[p%N]=curstomers[p].leave;//该空闲下来的时间为该顾客离开的时间
window[p%N].push(p);//p放入该窗口的队列中
}
/*开始确定等在黄线外的人的离开时间*/
while(p<K){
/*每个人都每次从三个窗口的队头选一个离开时间最短的入队,
也就是最短的队*/
int minleave=curstomers[window[0].front()].leave;
int minwin=0;
for(int i=1;i<N;i++){
if(minleave>curstomers[window[i].front()].leave){
minwin=i;
minleave=curstomers[window[i].front()].leave;
}
}
/*找到队伍之后开始入队*/
window[minwin].pop();//服务好的人出队
window[minwin].push(p);
curstomers[p].leave=open[minwin]+curstomers[p].serve;
open[minwin]=curstomers[p].leave;
p++;
}
/*开始查询*/
int no;
for(int i=0;i<Q;i++){
cin>>no;
if(curstomers[no-1].leave-curstomers[no-1].serve>=540)
printf("Sorry\n");
else
printf("%02d:%02d\n",8+curstomers[no-1].leave/60,curstomers[no-1].leave%60);
}
return 0;
}