题目链接:点击打开链接
题目大意:
- 银行排队办理业务,有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
*/