银行排队问题之单队列多窗口服务[天梯赛 -- 栈和队列]

题目描述

在这里插入图片描述

输入样例
9
0 20
1 15
1 61
2 10
10 5
10 3
30 18
31 25
31 2
3

输出样例

参考文章

思路

队列模拟

存储结构:使用结构体,存储每一个客户的到达时间和处理时间==(最大为60,大于60的,按60处理)==;用两个数组分别存储每一个窗口的办理人数 和 该窗口结束上一次处理的时间点

具体流程:由于题目给定的顾客顺序是按照时间先后,因此我们顺序处理即可
1.依次遍历每一个窗口,用flag标记该客户是否需要等待。
①如果存在一个窗口,该窗口上一次结束处理的时间 <= 客户到达时间,则客户不用等待,则更新该窗口的处理结束时间和处理人数
②如果不存在,则需要找到结束最快的一个窗口,标记其窗口编号和处理结束时间(用于计算该客户的等待时间)
2.如果本次客户需要等待,用之前找到的最短等待窗口,更新该窗口的处理结束时间和处理人数,计算总的等待时间
3.所有客户处理完成后,遍历存储窗口结束时间的数组,取出最大值,即为最后完成时间

AC代码

#include <bits/stdc++.h>
using namespace std;
const int N = 20;
typedef struct Person
{
    int t, p; //到达时间 处理时间
}person;
person p;
queue<person> q;
int cnt[N], complete[N]; //记录每个窗口处理的人数 和 上一次处理完成的时间
int sum_complete, max_wait, last_complete;// 平均等待时间 、最长等待时间、最后完成时间
int main()
{
    int n, k;
    cin >> n;
    for(int i = 0; i < n; i ++)
    {
        int T, P;
        cin >> T >> P;
        if(P > 60) P = 60; //题目中要求最大处理时间为60
        p = {T, P};
        q.push(p); //入队
    }
    cin >> k;
    while(q.size()) //按照顺序,先到先处理
    {
        p = q.front();
        q.pop();
        bool flag = true; //标记当前的人是否需要等待,默认需要等待
        int min_complete = 0x3f3f3f3f, min_complete_pos = 0; //在需要等待的情况下,我们需要找到上一次结束处理最早的窗口
        
        for(int i = 0; i < k; i ++) //寻找合适的窗口
        {
            //上一次该窗口结束处理的时间 小于等于 本人的到达时间, 则无需等待
            if(complete[i] <= p.t) 
            {
                flag = false;
                cnt[i] ++; //该窗口处理的人数+1
                complete[i] = p.t + p.p; //更新该窗口结束上一次处理的时间
                break;
            }
            //记录上一次处理完成最早的窗口的结束时间 和 窗口编号
            if(min_complete > complete[i])
            {
                min_complete_pos = i;
                min_complete = complete[i];
            }
        }

        //需要等待
        if(flag)
        {
            int temp_wait = min_complete - p.t; //等待的时间为 上一次该窗口结束处理的时间 - 本人到达时间
            sum_complete += temp_wait;
            max_wait = max(temp_wait, max_wait); //更新最大等待时间
            cnt[min_complete_pos] ++; //对应窗口处理人数+1
            complete[min_complete_pos] = min_complete + p.p; //更新对应窗口的结束上一次处理的时间
        }
    }
    for(int i = 0; i < k; i ++) last_complete = max(last_complete, complete[i]);
    printf("%.1f %d %d\n", sum_complete *1.0 / n, max_wait, last_complete);
    for(int i = 0; i < k; i ++)
    {
        if(i != k - 1) printf("%d ", cnt[i]);
        else printf("%d\n", cnt[i]);
    }
    return 0;
}

欢迎大家批评指正!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值