📅  最后修改于: 2023-12-03 15:12:36.565000             🧑  作者: Mango
此为GATE CS 2018的一道题目,第65章,主要考察计算机科学知识。
有n个人要通过一扇宽度为k的门,每个人的宽度为1,每次只能通过一个人,一开始门是关闭的。当一人通过门后,需要等待t时间才能再次打开门让下一个人通过,每个人通过的时间相同。现在告诉你每个人通过门的时间,你需要计算所有人都通过门需要的最短时间。
第一行为三个整数n, k, t,分别表示人数,门的宽度,和两个人通过之间需要的时间。
第二行包含n个空格分隔的正整数,表示每个人通过门所需要的时间。
仅包含一个整数,表示所有人都通过门需要的最短时间。
5 3 5
3 7 6 8 1
36
首先第一个人通过,时间为3,门关闭等待5秒。
第二个人通过,时间为7,门关闭等待5秒。
第三个人通过,时间为6,门关闭等待5秒。
第四个人通过,时间为8,门关闭等待5秒。
最后一个人通过,时间为1,共用时间为3 + 5 + 7 + 6 + 8 + 5 + 1 = 35。
本题其实可以采用模拟的方法直接进行模拟,不过需要仔细思考时间的算法。
为了提高模拟的效率,可以通过优先队列来模拟,每一次选取需要通过的人时,选取需要通过时间最少的人,如果有时间相同的,则选取序号最小的人。
经过推算可以得到完整的代码如下:
#include<bits/stdc++.h>
using namespace std;
long long read() {
long long x=0,f=1,c=getchar();
for (; !isdigit(c); c=getchar()) f=c=='-'?-1:f;
for (; isdigit(c); c=getchar()) x=(x<<1)+(x<<3)+(c^48);
return f*x;
}
long long n,k,t,a[1000005];
struct node {
long long idx,w;
bool operator < (const node &tmp) const {
if (w == tmp.w) {
return idx > tmp.idx;
}
return w > tmp.w;
}
};
priority_queue<node> q;
int main() {
n=read(); k=read(); t=read();
for (int i=1; i<=n; i++) {
a[i]=read();
}
for (int i=1; i<=n; i++) {
if (q.size() < k) {
q.push({i,a[i]+t});
}
else {
node top=q.top();
q.pop();
long long ni=top.idx,w=max(top.w,a[i])+t;
q.push({ni,w});
}
}
long long ans=0;
while (q.size()) {
node top=q.top(); q.pop();
ans=max(top.w,ans);
}
printf("%lld\n",ans-t);
return 0;
}
在C++中,$priority_queue$的默认是最大堆,在比较方法中需要自己实现,结构体内需要使用"<"符号,C++会重载"<"符号来实现排序。