题目链接:点击查看
题目大意:模拟银行服务的过程,输出每个客户的平均等待时间
题目分析:类似的银行服务模拟题,不过与之前那个题不太一样的是,这一次所需要统计的信息变少了,只需要统计一下每个客户的平均等待时间,加上每个客户到达银行的时间也不再统一,我们需要重新制定规则
最后还有一个坑点,就是只要用户在银行下班之前到达银行,那么无论多晚该用户都可以完成服务,所以需要统计等待时间,相对的,所有超过下班时间到达的用户,都不算数,最后计算平均值得时候也不用算上他们
具体实现的话,我还是用一层for循环当秒表用,每次走一秒,判断用户当前的情况,需要注意的是,因为在输入的时候就已经将不合法的用户排除在外了,所以我们秒表的下限是早晨八点,上限必须设置到第二天一点,也就是25点,当然设大了也没关系,一开始我设置了一个1700点,一样能过,因为有一个剪枝,所以并不会因为这个上限过大而超时,反而会因为上限过小而答案错误
这里就对应着最后一个测试点了:
为什么上限设置到下午五点会答案错误呢?因为整个程序模拟的是在秒表下限到上限中用户的等待时间的,若超过了下班时间,则还在排队的用户就没办法记录了,我们需要将上限设置的大一点才行,比如随便举个例子:
2 1
17:00:00 60
16:59:59 60
正确答案应该是30分钟吧(60/2),这样一个例子就能让银行的工作时间到达下午七点,若再来几组相似的样例,银行工作的上限会变得很大很大,不过这个题目还算是良心的,将时间设到第二天凌晨一点就能过掉了。。
代码:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> #include<unordered_map> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int N=1e4+100; struct Node { int time; int remain; Node(){} Node(int TIME,int REMAIN) { time=TIME; remain=REMAIN; } bool operator<(const Node& a)const { return time>a.time; } }; int n,m; int win[110]; queue<Node>wait;//在排队的人 priority_queue<Node>line;//所有人 bool check() { for(int i=1;i<=m;i++) if(win[i]) return false; return true; } int main() { // freopen("input.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int h,m,s,temp; scanf("%d:%d:%d %d",&h,&m,&s,&temp); if(17*60*60<h*60*60+m*60+s) continue; line.push(Node(h*60*60+m*60+s,temp*60)); } n=line.size(); int ans=0; for(int i=1;i<=m;i++)//先让提前来的人去窗口前面等着 { if(line.empty()||line.top().time>=8*60*60)//如果提前来的人没了 break; Node cur=line.top(); line.pop(); win[i]=cur.remain; ans+=8*60*60-cur.time; } while(line.size()&&line.top().time<8*60*60)//提前来的人很多,就先排队,并记录等待时间 { Node cur=line.top(); line.pop(); wait.push(cur); ans+=8*60*60-cur.time; } for(int i=8*60*60;i<=25*60*60;i++)//枚举秒 { if(check()&&line.empty()&&wait.empty())//没人了 break; if(!line.empty()&&line.top().time==i)//新来了一个人,先去排队 { wait.push(line.top()); line.pop(); } for(int j=1;j<=m;j++)//枚举每一个窗口 { if(win[j])//还有人在办手续 win[j]--;//时间-1s if(!win[j])//窗口没人了 { if(!wait.empty())//还有人在排队 { win[j]=wait.front().remain;//补上来 wait.pop(); } } } ans+=wait.size(); } printf("%.1f\n",1.0*ans/60/n); return 0; }