题意:
银行有n个窗口,每个窗口最多可以有m个人排队;(!!!注意:这些人不是按照顺序自己随便选窗口的,只能按照顺序从窗口1-n排)
如果n个窗口排满的话,剩下的人要站在黄线后面,等到有窗口队列不满的时候,再挨个过去排队;过去排队的时候优先选队列人数少的,人数少的一样的话选标号小的窗口
思路:
用队列表示窗口的队列,队列里面存的是每个人结束的时间,
a[] 表示每个人办业务时间,b[]表示每个人办完业务结束时刻,c[]表示每个窗口当前所有人办完业务的时刻
先把前面 n*m 个人(如果够的话)顺序放入队列;剩余黄线外面的人,挨个往里面放
(开始时错误代码以为前n*m个人每人按最优入队呢:错误如下https://blog.csdn.net/xiang_6/article/details/100135748)
#include<bits/stdc++.h>
#include<cstring>
#define FI first
#define SE second
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 1000 + 7;
const int maxd = 100 + 7;
const int INF = 0x7f7f7f7f;
int n, m, k, q;
int a[maxn], b[maxn]; // 每个顾客的办公时间和结束时刻
int c[maxd]; // 每个窗口最晚空闲时刻
queue<int> qu[maxd]; // 窗口队列(结束时刻)
int getid2() {
int res, min_ = INF;
for(int i = 1; i <= n; ++i) {
if(qu[i].size() == 0) continue;
if(qu[i].front() < min_) {
min_ = qu[i].front();
res = i;
}
}
return res;
}
void init() {
int M = n*m, pos = 1;
for(int i = 1; i <= m; ++i) {
for(int j = 1; j <= n; ++j) {
if(pos <= k) {
c[j] += a[pos];
b[pos] = c[j];
qu[j].push(c[j]);
}
pos++;
}
}
for(int i = M+1; i <= k; ++i) {
int id = getid2();
c[id] += a[i];
b[i] = c[id];
qu[id].push(c[id]);
qu[id].pop();
}
}
int main() {
scanf("%d%d%d%d", &n, &m, &k, &q);
for(int i = 1; i <= k; ++i) {
scanf("%d", &a[i]);
}
init();
int t;
for(int i = 1; i <= q; ++i) {
scanf("%d", &t);
if(b[t]-a[t] < 540) {
printf("%02d:%02d\n", (8+b[t]/60), (b[t]%60));
}
else {
puts("Sorry");
}
}
return 0;
}