PAT 1017 Queueing at Bank

题目描述

英文

在这里插入图片描述

中文大意

输入N个用户, 现有K个窗口,计算这些用户的平均等待时间
已知客户的 到达时间需要的服务时间,按照先来先服务的原则进行服务
银行的服务时间为 08:00 - 17:00,如果在 08:00 之前来了,就等到08:00,如果在17-01 及之后来了,那就不能再被服务

样例

在这里插入图片描述

思路分析

构建一个 struct 来存储客户的 到来时间服务时间,然后按照到来时间进行排序,此处用了 <algorithm> 的 sort 函数
然后参考 柳神的博客,维护了一个 优先队列(最小堆),里面存放的是 窗口的业务完毕时间(也就是可以开始服务的时间),此处把时间秒化 也是参照博客。
看到题目大概知道要用 优先队列,但是对C++的优先队列并不是很清楚,还有 vector 的用法也不太清楚。之后有时间会写个博客

易错点
cnt:不能用 N 来计算,要单独使用 cnt ,把17-00 以后的客户去掉
最后的输出不能写成 (double)total/(60),必须要用 60.0

code

#include <iostream>
#include <queue>
#include <algorithm>

using namespace std;
#define MAX 10005
#define START_TIME 8 * 3600
#define END_TIME 17 * 3600

typedef struct person {
    int come, time;
};

int cmp(person p1, person p2) {
    return p1.come < p2.come;
}

/**
 * 17:00:01 = 61201
 * 08:00:00 = 28800
 * @return
 */
int main() {
    person p[MAX];  // 顾客队列
    int cnt = 0;    // 有效顾客数
    int total = 0;  // 总时间
    int N, K;       // N: 顾客数 K: 窗口数
    scanf("%d%d", &N, &K);
    for (int i = 0;i < N;i++) {
        // hh:mm:ss process
        int h, m, s, t, sum;
        scanf("%d:%d:%d %d", &h, &m, &s, &t);
        // 时间转换
        sum = h * 3600 + m * 60 + s;
        if (sum > END_TIME) continue;
        p[cnt].time = t * 60;
        p[cnt++].come = sum;
    }
    // 按到达时间进行排序比较
    sort(p, p + cnt, cmp);
    // 定义一个优先队列 (最小堆)
    priority_queue<int, vector<int>, greater<int>> pq;
    for (int i = 0;i < K;i++)
        pq.push(START_TIME);
    for (int i = 0;i < cnt;i++) {
        // 窗口的最早可服务时间 <= 到来时间   即到来便可服务 无需等待
        // 初始化时已将最早可服务时间设置为 08:00
        if (pq.top() <= p[i].come) {
            // 该顾客的结束时间
            pq.push(p[i].come + p[i].time);
            pq.pop();
        } else {
            total += pq.top() - p[i].come;
            pq.push(pq.top() + p[i].time);
            pq.pop();
        }
    }
    (!cnt) ? printf("0.0") : printf("%.1lf", ((double)(total/60.0) / (double) cnt));
}

题目链接

1017 Queueing at Bank (25分)

参考文章

STL里的priority_queue用法总结
Queueing at Bank (25)-PAT甲级真题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值