📜  门| GATE CS 2018 |简体中文第65章(1)

📅  最后修改于: 2023-12-03 15:12:36.565000             🧑  作者: Mango

门| GATE CS 2018 |简体中文第65章介绍

简介

此为GATE CS 2018的一道题目,第65章,主要考察计算机科学知识。

题目描述

有n个人要通过一扇宽度为k的门,每个人的宽度为1,每次只能通过一个人,一开始门是关闭的。当一人通过门后,需要等待t时间才能再次打开门让下一个人通过,每个人通过的时间相同。现在告诉你每个人通过门的时间,你需要计算所有人都通过门需要的最短时间。

输入格式

第一行为三个整数n, k, t,分别表示人数,门的宽度,和两个人通过之间需要的时间。

第二行包含n个空格分隔的正整数,表示每个人通过门所需要的时间。

输出格式

仅包含一个整数,表示所有人都通过门需要的最短时间。

样例输入1
5 3 5
3 7 6 8 1
样例输出1
36
样例解释1

首先第一个人通过,时间为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++会重载"<"符号来实现排序。