题目链接:点击打开链接
题目大意:
银行排队办理业务,有n个窗口,每个窗口前有黄线,黄线内最多排m个人,剩下的人在黄线外等候
给出k个人,并给出他们办理业务所需要的时间time,查询p个人的办理业务结束时间,如果开始办理业务时超过了17:00,输出sorry
08:00开始办理业务,17:00结束办理业务,如果业务已经开始办理,就继续办理直到办理业务结束窗口才关门。
如果某个窗口有人办理业务结束,黄线外的人去那个窗口的队尾等候,如果两个窗口同时有人办理业务结束,就选择窗口号较小的
解题思路:
从17:00前就已经开始服务的,虽然最终的服务时间超过五点,也不是Sorry,而只有从17点之后才会被开始服务的,会是Sorry。这个很关键,不然会有答案错误的案例。
每个顾客进入到一个队伍之后,就不能再离开这个队伍,即使其他队伍中已经没有人了,也只能等当前队伍前面的人结束之后在本队伍接受服务。
大循环用时间来控制,每分钟轮询检测。
AC 代码
#include<bits/stdc++.h> #include<cmath> #define mem(a,b) memset(a,b,sizeof a); #define INF 0x3f3f3f3f using namespace std; typedef long long ll; struct node { int id,rest; node(){} node(int id,int rest):id(id),rest(rest){} friend bool operator<(node n1,node n2) { if(n1.rest==n2.rest) return n1.id>n2.id; // 小->大 return n1.rest<n2.rest; // 大->小 } }; priority_queue<node> pq; // 维护有空窗口的状态 queue<int> q[21]; // int 为客户的 id(从 1 开始) int w,cap,n,k; // 窗口数 窗口容量 客户数 查询次数 int ans[1010], cost[1010]; // 结果 耗时 void init() { mem(ans,-1); mem(cost,0); // ans -1 是为了标记那些没有被处理的客户,Sorry for(int i=0;i<21;i++) while(!q[i].empty()) q[i].pop(); } void print(int mm) { printf("%02d:%02d\n",mm/60,mm%60); } int main() { while(~scanf("%d%d%d%d",&w,&cap,&n,&k)) { init(); for(int i=1;i<=n;i++) scanf("%d",&cost[i]); // 初始化客户排队 int id=1; for(int i=1;i<=cap;i++) for(int j=1;j<=w;j++) q[j].push(id++); // 高能啊,t=[1,540),因为客户消耗的时间一定是正整数, // 540 开区间是因为正好这时候是处理最后一批正在服务的客户,放到最后有一个for来处理, // 等于的话,否则当中会有把 >540 的情况也算进去。(原本只过了3个点,就去了这个等号后 AC!) for(int t=1;t<540;t++) { while(!pq.empty()) pq.pop(); for(int i=1;i<=w;i++) { if(!q[i].empty()) { int idx=q[i].front(); if(t==cost[idx]) { q[i].pop(); ans[idx]=8*60+t; // 提前计算好下个该队下个客户的出来时间 idx=q[i].front(); cost[idx]+=t; pq.push(node(i,cap-q[i].size())); // 因为只有走了才有空位,每次 q 都会尽可能的补满 } } } // 维护有空窗口的队列,并且客户入队 int isEpy=1; node nd; while(isEpy) { isEpy=0; while(!pq.empty() && id<=n) { nd=pq.top(); pq.pop(); q[nd.id].push(id++); nd.rest--; if(nd.rest>0) pq.push(nd); isEpy=1; } } } // 维护最后到结束点还在处理业务的客户,只处理一批即可,因为下一批已经关门(被赶走)了 for(int i=1;i<=w;i++) { if(!q[i].empty()) { int idx=q[i].front(); q[i].pop(); ans[idx]=8*60+cost[idx]; } } int sel; while(k--) { scanf("%d",&sel); if(ans[sel]==-1) puts("Sorry"); else print(ans[sel]); } } return 0; } /* 2 2 7 5 1 2 6 4 3 535 2 3 4 5 6 7 */