问题描述:N<20个窗口,每个窗口最多M<10人,K<1000个顾客,Q<1000个查询;前N个人开始时间都是8:00;已知每一个人的处理时间,求每个人的事情办理完的时间。
解题思路:给每个窗口设置一个队列,初始化前N*M(或K)个人,事件驱动为一个人最先处理完,然后将下一个人添加到该窗口的队列中。具体思路为:给每个窗口设置当前顾客完成交易所需的时间t[i],选择t[i]中最小的值,完成一次更新(完成的窗口更新为该队列下一个顾客的处理时间,其他窗口全部减去该值)
AC代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x0fffff
#define CLOSE 17*60
vector<int>window,dealtime,process;
queue<int>winque[20];
int N,M,K,Q,T=8*60;
bool update(int v)
{
int i,m=INF,k=0,close=0;
for(i=0;i<N;++i){//选择每个窗口里处理时间最小的窗口
if(winque[i].size()){
if(dealtime[winque[i].front()]<m){
m=dealtime[winque[i].front()];k=i;
}
}else ++close;
}
if(close==N)return 1;
else{
for(i=0;i<N;++i){//更新所有窗口当前处理时间
if(winque[i].size()){
dealtime[winque[i].front()]-=m;
}
}
//if(T<CLOSE)dealtime[winque[k].front()]=T+m;//错在这,本来是17:00之前插入的,一个处理时间可能分为了很多片段,导致完成时超过了CLOSE
//else if(T==CLOSE&&m==0)dealtime[winque[k].front()]=T;
//else dealtime[winque[k].front()]=-1;
T+=m;
dealtime[winque[k].front()]=T;
if(T-process[winque[k].front()]>=CLOSE)dealtime[winque[k].front()]=-1;//处理之前超过17:00
winque[k].pop();
if(v<K){//后面还有人
scanf("%d",&dealtime[v]);
process[v]=dealtime[v];
if(T<CLOSE)winque[k].push(v);//未关门
else dealtime[v]=-1;
}
return 0;
}
}
int main()
{
freopen("test.txt","r",stdin);
scanf("%d %d %d %d",&N,&M,&K,&Q);
++K;
dealtime.resize(K);process.resize(K);
int i,j,k,t;
for(i=0,k=1;i<M&&k<K;++i){//前M*N个人排好队
for(j=0;j<N&&k<K;++j,++k){
winque[j].push(k);
scanf("%d",&process[k]);
dealtime[k]=process[k];
}
}
while(1){
if(update(k))break;//更新,
else ++k;
}
while(Q--){
scanf("%d",&t);
if(dealtime[t]>0)printf("%02d:%02d\n",dealtime[t]/60,dealtime[t]%60);
else printf("Sorry\n");
}
return 0;
}