PAT_A1017
PAT甲级1017.
目录
A1017
题目
样例
输入:
7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10
输出:
8.2
思路和坑点
将有效的顾客建立队列,这里利用map容器的有序性,直接使用map记录每位顾客,从而形成有序的队列,映射的值为顾客的时间花费,按照要求,每位顾客最长为60分钟,输入时直接处理。
另一个问题在于窗口的模拟,窗口使用数组记录每个窗口服务结束的时间,如果窗口到达结束时间,而且队伍不空,且队伍中的顾客已经到了,则入队服务并计算等待时间。
坑点
判定时间结束的的标志,应该是顾客队列空,而不是17点。因为所有的有效记录都是需要服务的,所以有可能有人17点之前到了,但是排到17点以后才接受服务,测试点5的情况便是如此。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define st 8*3600
#define ed 17*3600
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif
int n,k;
cin>>n>>k;
map<int,int> custom; //顾客队列
vector<int> window(k,st); //窗口模拟
for(int i=0;i<n;i++){ //输入
int h,m,s,cost;
scanf("%d:%d:%d %d",&h,&m,&s,&cost);
int begin=h*3600+m*60+s;
if(begin<=ed){ //有效记录才保存
cost=cost>60?3600:cost*60; //服务时间上界判定
custom[begin]=cost; //保存记录
}
}
if(custom.size()==0){ //队列如果没有人特判,因为0人无法平均
cout<<"0.0";
}
else{
n=custom.size();
int cnt=0;
int flag=0;
for(int time=st;;time++){ //判定终点应该是顾客队列位空,而不是银行关门时间
for(int i=0;i<k;i++){
if(custom.size()==0){ //队列空是退出循环
flag=1;break;
}
if(window[i]<=time){ //窗口时间到时且队列中有人时
auto it=custom.begin(); //去队首顾客进行服务
if(it->first<=time){
cnt+=time-it->first; //计算等待时间
window[i]=time+it->second; //更新窗口结束时间
custom.erase(it); //将纳入服务的顾客移出队列
}
}
}
if(flag==1) //循环结束判定,两层,因此判定两次
break;
}
printf("%.1f",1.0*cnt/(60*n));
}
return 0;
}