分析:队列的常规操作,理清思路非常关键。
#include<cstdio>
#include<queue>
using namespace std;
const int maxn = 1e3+10;
queue<int> win[30];
int serv[maxn], res[maxn], wintime[30];//serv[i]:第i个人的服务时间 wintime[i]:第i个窗口当前的时间
void pop(int i){
int top = win[i].front(); //top为第i个窗口最前面的那个人的id
win[i].pop();
res[top] = wintime[i] + serv[top]; //top的离开时间为第i个窗口的时间加上服务时间
wintime[i] = res[top]; //更新第i个窗口现在的时间
}
int main(){
//freopen("aa.txt", "r", stdin);
int n, m, k, q, num, cnt = 1, endtime = 17*60;
scanf("%d %d %d %d", &n, &m, &k, &q);
for(int i = 1; i<=k; i++)
scanf("%d", &serv[i]);
for(int i = 0; i<n; i++)
wintime[i] = 8*60; //初始化每个窗口当前的时间为8点
for(int i = 0; cnt<=k && cnt<=m*n; i++)
win[i%n].push(cnt++); //初始化队列 排成m*n
while(cnt <= k){
int u = 0, minn = wintime[0] + serv[win[0].front()];
for(int i = 1; i<n; i++){
int tem = wintime[i] + serv[win[i].front()];
if(tem < minn){
minn = tem;
u = i; //找出当前服务完第一个人时间最小的窗口
}
}
if(wintime[u] >= endtime) break; //大于17点即不用入队了
pop(u); //把第u个窗口队首出队
win[u].push(cnt++); //然后入队
}
for(int i = 0; i<n; i++) //对每一个窗口进行出队操作,直到队空或者大于结束时间
while(!win[i].empty() && wintime[i]<endtime)
pop(i);
for(int i = 0; i<q; i++){
scanf("%d", &num);
if(res[num] == 0) printf("Sorry\n");
else printf("%02d:%02d\n", res[num]/60, res[num]%60);
}
return 0;
}