复杂模拟 | 1014 模拟K个同时到来的人在N个窗口,每个窗口只能站M个人的银行排队
这题我以为还是之前银行排队的思路,但是做着做着就做不下去了了。看了答案我才理解到底是什么个思路。
是这样的:不同于之前排队的题,这里的K个人是同时到来的。所以首先应该让K个人的前N*M(也就是黄线内的容量)个人入队,并且是循环如N个对,直接让 i 循环到K,然后做 i %N的取余操作得到窗口索引。
入队完毕后,对于剩下的人,让他们依次选择出队最早的每个窗口。
所以,用一个Window结构体来记录每个窗口的信息:一个排队的队列,出队时间,服务结束时间。
并且要注意的是Sorry的输出情况,请看题面:
Note that since the bank is closed everyday after 17:00, for those customers who cannot be served before 17:00, you must output "Sorry" instead.
题面说的是在17:00之前无法得到服务的。所以要用服务结束时间 finish[index] 减去 服务时间 serve[index] 得到开始时间。用这个时间进行判断。
AC代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 1010 #define MAX (1<<30)+1 #define V vector<int> using namespace std; int Format2minute(int h,int m){ return h*60+m; } void printTime(int time){ O("%02d:",time/60); O("%02d\n",time%60); } struct Window{ int endTime,popTime; queue<int>q; }window[20]; int serve[1010]; //每个人的服务时间 int finish[1010]; //每个顾客的完成时间 int main(){ // freopen("1014.txt","r",stdin); //窗口、等待数、顾客、查询数 int N,M,K,Q,i,j; I("%d%d%d%d",&N,&M,&K,&Q); int startTime=Format2minute(8,0); int endTime=Format2minute(17,0); FF(i,N){ window[i].popTime=window[i].endTime=startTime; } FF(i,K) I("%d",&serve[i]); int index=0; FF(i,min(K,N*M)){ index=i%N; //窗口索引 window[index].q.push(i); window[index].endTime+=serve[i]; if(i<N) window[i].popTime=serve[1010];//对于第一个入队的,更新出队时间 finish[i] =window[index].endTime; } while(i<K){//处理剩下的顾客 //找到最先处理完的队伍 int minTime=MAX; FF(j,N){ if(window[j].popTime<minTime){ minTime=window[j].popTime; index=j; } } Window& w=window[index]; w.q.pop(); w.q.push(i); w.endTime+=serve[i]; w.popTime+=serve[w.q.front()]; finish[i]=w.endTime; i++; } while(Q--){ I("%d",&index); int ans=finish[index-1]; if(ans-serve[index-1]>=endTime) puts("Sorry"); else printTime(ans); } return 0; }