【1014 30 大模拟】 Waiting in Line
传送门
题意
\(n\) 个窗口,每个窗⼝可以排队 \(m\) 人。有 \(k\) 位用户需要服务,给出了每位⽤户需要的 \(minute\) 数,所有客户在 \(8\) 点开始服务,如果有窗⼝还没排满就入队,否则就在⻩线外等候。如果有某一列有一个⽤户⾛了服务完毕了,⻩线外人就进来一个。如果同时就选窗⼝数小的。求 \(q\) 个人的服务结束时间。
数据范围
\(1\leq n\leq 20\)
\(1\leq m\leq 10\)
\(1\leq k\leq 1000\)
\(1\leq q\leq 1000\)
题解
- 只有所有的窗口的所有队列满的时候才会考虑选取时间最小的问题
- 维护每个队列的最后一个人的完成时间,既可以用来更新新加进来的结束时间,又能判断当前是否超过介质时间
tie(int, double, char, ...),将值结合为tuple,方便按照顺序进行大小排序
Code
#include <bits/stdc++.h>
using namespace std;
struct customer {
int endtime, idx, window;
customer(int a, int b, int c) : endtime(a), idx(b), window(c) {}
bool operator < (const customer& a) const {
return tie(endtime, window) > tie(a.endtime, a.window);
}
};
int main() {
int n, m, k, q; cin >> n >> m >> k >> q;
int deadline = 17 * 60;
vector<int> finish(k, -1);
priority_queue<customer> customers;
vector<int> windows(n), time(n, 8 * 60);
for (int i = 0; i < k; i++) {
int x; cin >> x;
if (customers.size() == n * m) {
auto it = customers.top();
customers.pop();
windows[it.window]--;
}
int mi = min_element(windows.begin(), windows.end()) - windows.begin();
windows[mi]++;
if (time[mi] >= deadline) continue;
time[mi] += x;
customers.push(customer(time[mi], i, mi));
finish[i] = time[mi];
}
for (int i = 0; i < q; i++) {
int x; cin >> x; x--;
if (finish[x] == -1) {
cout << "Sorry" << endl;
} else {
printf("%02d:%02d\n", finish[x] / 60, finish[x] % 60);
}
}
}

浙公网安备 33010602011771号