好久没有做pat了,重新开刷
本想从这道水题入手可以快点,结果却惨遭滑铁卢,到第二天才全部通过
废话说完看题,模拟题,模拟的是多窗口排队。
建议把时间统一转化为秒做处理。
我选择了用map存储依次到达的顾客(题设保证了到达时间都不相同),用priority_queue模拟窗口业务过程。
以顾客为程序的演进标度,即循环遍历map,相机对优先队列做操作。
在初始阶段进队直到到达窗口人数后,始终保持优先队列中元素数量一出一进。
在到达时间小于实际开始服务时间的顾客入队时,累加其等待时间。
值得注意的是,虽然这种方法一定程度与事实是不符合的(eg:新元素进队时可能实际上不止一个旧元素应当出队),但这并不影响对时间的计算。
point:窗口数可能多于17:00前的顾客数,此时直接输出0.0即可
优先队列默认是最大元素出队,可以重载也可以写比较函数,我是将其转化为负数处理的。
#include<stdio.h>
#include<map>
#include<queue>
using namespace std;
int main()
{
int n,k,i,t,time,t1,t2,free,wait,current,count;
char s[10];
int tt[10005];
scanf("%d %d",&n,&k);
t1=8*60*60;
t2=17*60*60;
map<int,int> m;
map<int,int>::iterator p;
priority_queue<int> q;
wait=0;
if(n<=0||k<=0)
{
printf("0.0\n");
return 0;
}
for(i=0;i<n;i++)
{
scanf("%s %d",&s,&t);
time=((s[0]-'0')*10+(s[1]-'0'))*60*60+((s[3]-'0')*10+(s[4]-'0'))*60+((s[6]-'0')*10+(s[7]-'0'));
if(t>60)
t=60;
if(time<=t2)
{
m.insert(make_pair(time,t*60));
}
}
free=k;
current=t1;
p=m.begin();
count=m.size();
if(count<=k)
{
printf("0.0\n");
return 0;
}
while(p!=m.end())
{
if(free>0)
{
while(free>0&&p!=m.end())
{
--free;
if(p->first>=current)
{
q.push(-p->first-p->second);
}
else
{
wait+=current;
wait-=p->first;
q.push(-current-p->second);
}
++p;
}
}
else if(!q.empty())
{
current=-q.top();
q.pop();
++free;
}
}
double ans = double (wait);
ans/= (count*60.0);
printf("%.1lf\n",ans);
return 0;
}
错误记录:
本来把所有8:00前到达的顾客的到达时间都标度为8:00然后置于multimap中。
但无法通过第一个case
最后发现这个做法实际上破坏了8:00前到达的顾客的到达先后顺序,当8:00前到达的顾客的到达时间数量多于窗口数时,其先后顺序就会影响整体的等待时间
看来是对STL容器的属性有所遗忘所导致的错误
以上