【PAT甲级题解记录】1017 Queueing at Bank (25 分)

【PAT甲级题解记录】1017 Queueing at Bank (25 分)

前言

Problem:1017 Queueing at Bank (25 分)

Tags:模拟

Difficulty:剧情模式 想流点汗 想流点血 死而无憾

Address:1017 Queueing at Bank (25 分)

问题描述

一个银行K个窗口,每个窗口接待一个客户,营业时间8:00到17:00,之前到达的需要等,之后到达的不接待。

给出N个客户的到达时间和需要服务时间,求平均等待时间。

解题思路

坑点:

  • 首先需要明确第一个坑人的点(测试点5):题目中 "and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average."的意思是comes too late的才不计入平均,但是只是由于等待前面用户才超下班时间的还是需要算的。
  • 第二个坑点是等待时间不算服务时间,有时候想偏了连答案怎么来的都不知道。
  • 还有一个坑点就是窗口数量可能大于实际能来的人数(测试点1)

思路:

  • 我们的任务就是维护一个结束时间数组,记录各个窗口的客户结束的时间,在维护这个数组的同时计算出等待时间。
  • 细节实现上我采取了一个结构体保存客户的到达时间和需要服务时间,并将其组成一个有序的客户数组。再定义一个大小为K的数组存储当前窗口服务结束时间(窗口数组)。
  • 将客户分为两拨人处理。第一拨人是最开始来的人,可以直接用来初始化窗口数组;然后遍历第二拨人,每次从窗口数组里挑一个最先结束的,然后从后面排队的第二拨人中拿第一个去更新就行了。

(PS.这道题好像并不考虑被接待客户数量为0的情况)

参考代码


#include<cstdio>
#include<iostream>
#include<iomanip>
#include<vector>
#include<algorithm>

using namespace std;
int N, K; // N customers, K windows
const int MIN_TIME = 8 * 3600;
const int MAX_TIME = 17 * 3600;

struct Customer {
    int arr_time, proc_time;

    Customer(int t1, int t2) : arr_time(t1), proc_time(t2) {}
};

vector<Customer> customers;

bool cmp(const Customer &c1, const Customer &c2) {
    return c1.arr_time < c2.arr_time;
}

void init() {
    cin >> N >> K;
    for (int i = 0; i < N; i++) {
        int t1, t2, t3, t4;
        scanf("%d:%d:%d %d", &t1, &t2, &t3, &t4);
        Customer c(t1 * 3600 + t2 * 60 + t3, t4 * 60);
        if (c.arr_time <= MAX_TIME) {
            customers.push_back(c);
        }
    }
    sort(customers.begin(), customers.end(), cmp);
}

void solve() {
    vector<int> now_time(K, 0);
    int turn = 0;
    int sum_time = 0;
    int num = customers.size();
    if (num == 0) {
        cout << "0.0" << endl;
    }
    // 最开始来的人
    for (int i = 0; i < min(K, num); i++) {  // 注意i被最大人数和最大窗口数同时限制,漏了窗口数会出现下标越界
        int begin_time = max(MIN_TIME, customers[turn].arr_time);
        sum_time += begin_time - customers[turn].arr_time;
        now_time[i] = begin_time + customers[turn].proc_time;
        turn++;
    }
    // 后面来的人
    while (turn < num) {
        int min_i = 0;
        for (int i = 1; i < K; ++i) {
            if (now_time[i] < now_time[min_i]) min_i = i;
        }
        int begin_time = max(now_time[min_i], customers[turn].arr_time);
        sum_time += begin_time - customers[turn].arr_time;
        now_time[min_i] = begin_time + customers[turn].proc_time;
        turn++;
    }

    cout << fixed << setprecision(1) << double(sum_time) / 60 / num << endl;

}

void solution_1017() {
    init();
    solve();
}

int main() {
    solution_1017();
    return 0;
}

总结

题目意思中会出现一些可能会带一点点歧义的语句,思考清楚一般来说题目是没有问题的,大不了都试一下反正没有罚时。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值