其他分享
首页 > 其他分享> > 1017 Queueing at Bank (25分) 思路详解+满分代码

1017 Queueing at Bank (25分) 思路详解+满分代码

作者:互联网

题目

Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.

Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.

Input Specification:
Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤10^4) - the total number of customers, and K (≤100) - the number of windows. Then N lines follow, each contains 2 times: HH:MM:SS - the arriving time, and P - the processing time in minutes of a customer. Here HH is in the range [00, 23], MM and SS are both in [00, 59]. It is assumed that no two customers arrives at the same time.

Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.

Output Specification:
For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.

Sample Input:
7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10
Sample Output:
8.2

题目大意

有n个客户(不超过10000)来银行办理业务,银行有k个窗口(不超过100),银行早上8点开始服务,下午5点结束服务,17:01及以后到达的客户无法被服务;给出这n个客户的到达时间和他们办理业务要花费的时间,最终输出所有客户的平均等待时间,单位为min,精确到小数点后1位。

思路分析

这个题目与之前那个 Waiting In Line 的区别在于,所有用户都必须在黄线外等待,然后每当一个窗口结束一个服务,他就过去排队,所以这个题目本身应该是比上个题简单的,但奈何脑子太笨真不怎么想得出来,倒是上个题目自己做出来了。。。奇葩。

// 定义:priority_queue<Type, Container, Functional>
//  Type 就是数据类型,Container 就是容器类型
// (Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),
// Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型
// 默认是大顶堆

//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;

// greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。
// 其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

满分代码

#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;

struct People {
    // 全部以秒为单位进行记录
    int arrive_time, process_time;
} people[10000];

// 用于升序排序
bool cmp(People c1, People c2) {return c1.arrive_time < c2.arrive_time;} 

int main() {
    // 银行开始服务时间,结束服务时间
    int bank_open_time = 8 * 3600, bank_close_time = 17 * 3600;
    // n 个人,k 个窗口
    int n, k;
    cin >> n >> k;
    // 记录有效的,被服务的客户数目
    int index = 0;
    // 所有被服务的客户的等待时间
    int total_wait_time = 0;
    int h, m, s, p;
    for (int i = 0; i < n; ++i) {
        scanf("%d:%d:%d %d", &h, &m, &s, &p);
        int time = h * 3600 + m * 60 + s;
        // 在 17:00之后到达,不会被服务,不用记录,不用于计算平均时间
        if (time > bank_close_time) continue;
        // 保存这个客户记录,index+=1
        people[index].arrive_time = time;
        if (p > 60) p = 60; // 每个窗口服务不会超过1小时,相当于把他的占用时间改为1小时
        people[index].process_time = p * 60;
        index++;
    }
    // 根据到达时间进行排序
    sort(people, people + index, cmp);
    // 用一个优先队列维护k个窗口当前服务结束时间,使用小顶堆
    // 第二个参数必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector
    // greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
    // 默认实现的是大顶堆
    priority_queue<int, vector<int>, greater<int>> minheap;
    // 首先k个窗口都是8:00开始服务,相当于它当前服务的结束时间都是8:00
    while (k-- > 0)
        minheap.push(bank_open_time);
    // 顾客已经排好序了,逐个处理
    for (int i = 0; i < index; ++i) {
        // 最早结束服务的那个窗口服务在他来之前能够结束服务,甚至可能已经空了一会
        if (minheap.top() <= people[i].arrive_time) {
            // 不用等待
            // pop()相当于那个窗口结束上一个服务
            // 接着窗口为他服务,那么这个窗口这次的结束时间就是 【这个人来的时间+这个人需要的时间】
            minheap.push(people[i].arrive_time + people[i].process_time);
            // 本应该先结束服务再为他服务,但先pop()栈顶元素改变,我们得先保存top()
            minheap.pop();
        } else {
            // 他需要等 最早的那个窗口结束当前服务
            total_wait_time += minheap.top() - people[i].arrive_time;
            // 然后窗口结束服务,为他服务,最小堆pop()并插入新元素
            // 这里与上面的区别的是,窗口这次的结束时间是 【窗口上次的结束时间+这个人的等待时间】
            minheap.push(minheap.top() + people[i].process_time);
            // 本应该先结束服务再为他服务,但先pop()栈顶元素改变,我们得先保存top()
            minheap.pop();
        }
    }
    // 以分钟输出平均等待时间
    printf("%.1f", total_wait_time / 60.0 / index);

    return 0;
}

当然我是参考了大佬的代码的,不然怎么可能这么简洁呢?嘻嘻。

标签:25,00,窗口,int,Queueing,结束,time,服务,1017
来源: https://www.cnblogs.com/codervivi/p/12875514.html