1.题目大意:就是给你n个窗口,每个窗口有一条黄线,每条黄线内可以排m个人(也就是所有窗口可排m*n个),每个人处理事务都需要一定的时间,进了黄线就不能换队排队了。当黄线内的名额没有满的时候,就按顺序进入窗口。如果黄线外的人要进入,就得等到有空出来的位置才能进黄线内排队。要求输出每个请求者服务完毕的时间。注:银行从8点—17点接受请求,如超出,则返回Sorry
这个题一开始看了半天没理清楚什么意思,一直以为进了黄线还可以换位置(实际上不能换),就一直找哪个窗口处理最快,惨遭wa,然后看了柳婼大神的blog,借鉴了里面的思维,理清逻辑后,很快就ac了。
2.思路:其实当我们的黄线内的名额没有满的时候,能进就进。当满了的时候,就要考虑我下面这个人应该进哪个窗口等呢?如果我们知道每个窗口最快出来的人的出队的时间点,那么就好办了,选中这个窗口,一个pop和push就行了。那么怎么记录这个状态呢?我们给每个窗口一个poptime,就是这个窗口当前最快出队的人的出队的时间点,只需要每个窗口作比较,选出最快的那个,把候补的人放进这个窗口,然后更新poptime即可.同样的,我们想知道我刚入队的人他请求服务的时间是不是超过了17点,我们只需要设置一个endtime,来作为该窗口当前处理完所有请求时间点的说明.
所以本题的关键点在于poptime,endtime.
水平有限,还需要多多练习,理清里面的逻辑关系,再找到合适的方法,做到模拟有道。(逃~
#include<bits/stdc++.h>
using namespace std;
int times[1010];
struct node
{
int poptime,endtime;
queue<int> q;
};
int main ()
{
int n,m,k,qs;
scanf("%d%d%d%d",&n,&m,&k,&qs);
for(int i=1;i<=k;i++){
scanf("%d",×[i]);
}
vector<node> win(n+1);
vector<int> res(k+1);
vector<bool> sorry(k+1,false);
int index = 1;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(index<=k){
win[j].q.push(times[index]);
if(win[j].endtime>=540)
sorry[index] = true;
win[j].endtime += times[index]; //窗口结束时间==原来的+新的时间
res[index] = win[j].endtime; //index服务完成的时间
}
if(i==1){
win[j].poptime = times[index];
}
index++;
}
}
while(index<=k){
int tempmin = win[1].poptime;
int tempwin = 1;
for(int i=2;i<=n;i++){ //找出当前出队时间最短的窗口
if(win[i].poptime<tempmin){
tempmin = win[i].poptime;
tempwin = i;
}
}
win[tempwin].q.pop();
win[tempwin].q.push(times[index]);
win[tempwin].poptime += win[tempwin].q.front();
win[tempwin].endtime +=times[index];
if(win[tempwin].endtime-times[index]>=540)
sorry[index] = true;
res[index] = win[tempwin].endtime;
index++;
}
int po;
for(int i=0;i<qs;i++){
scanf("%d",&po);
if(sorry[po]==true) printf("Sorry\n");
else{
printf("%02d:%02d\n",(res[po]+480)/60,(res[po]+480)%60);
}
}
return 0;
}