对于这种排队处理问题,我们先定义一个二维窗口函数用于保存当前窗口的结束时间和处理过的人数,我们再定义一个总等待时间值,初始化为0。对于每一个顾客我们有到达时间和处理时间,我们先作为一个顾客进入银行,先找到等待时间最短的窗口,这个寻找过程我们用一个函数finds(int begin),传入的值是顾客的到达时间,具体查找函数如下
int findok(int arri)
{
int minn=0;
for(int i=0;i<wids;i++)
{
if(widow[0][i]<arri)widow[0][i]=arri;
if(widow[0][minn]>widow[0][i])minn=i;
}
widow[1][minn]++;
return minn;
}
其中我们有三个目的,如果当前窗口的结束时间小于我们当前顾客的到达时间我们就得将该顾客的到达时间赋给该窗口的结束时间,然后我们找出最小等待时间,并且最小等待时间的窗口使用人数加1.当我们找出了最小等待时间窗口后我们将该人的等待时间算出,在这里我们用一个简单的键值将最大等待时间保存下来,之后该窗口的结束时间再加上该顾客的被服务时间,这个就是我们的顾客处理工作。
之后我们考虑总等待时间,一个顾客的等待时间等于窗口结束时间-该顾客的到达时间。如果这个等待时间大于0,就将其加入总等待时间。
二者的具体实现代码如下
for(int i=0;i<hum[0].size();i++)
{
int minn=findok(hum[0][i]);
int wait=widow[0][minn]-hum[0][i];
if(wait>0)waitz+=wait;
if(wait>maxwait)maxwait=wait;
widow[0][minn]+=hum[1][i];
}
之后我们从每个窗口的结束时间里找出最大的就是我们的总结束时间。
所以我们这道题的具体代码如下
#include<bits/stdc++.h>
using namespace std;
vector<vector<int> >widow(2,vector<int>(10));
int wids;
int findok(int arri)
{
int minn=0;
for(int i=0;i<wids;i++)
{
if(widow[0][i]<arri)widow[0][i]=arri;
if(widow[0][minn]>widow[0][i])minn=i;
}
widow[1][minn]++;
return minn;
}
int main()
{
int peo;cin>>peo;int peoo=peo;
int waitz=0,maxtime=0,maxwait=0;
vector<vector<int> >hum(2);
while(peo--)
{
int work,arrive;cin>>arrive>>work;
if(work>60)work=60;
hum[0].push_back(arrive);
hum[1].push_back(work);
}
cin>>wids;
for(int i=0;i<hum[0].size();i++)
{
int minn=findok(hum[0][i]);
int wait=widow[0][minn]-hum[0][i];
if(wait>0)waitz+=wait;
if(wait>maxwait)maxwait=wait;
widow[0][minn]+=hum[1][i];
}
for(int i=0;i<wids;i++)
{
maxtime=max(widow[0][i],maxtime);
}
printf("%.1f %d %d\n",waitz*1.0/peoo,maxwait,maxtime);
cout<<widow[1][0];
for(int i=1;i<wids;i++)
{
cout<<" "<<widow[1][i];
}
}