银行排队问题之单窗口“夹塞”版

本文介绍了一种编程模拟,分析在银行排队时,顾客利用朋友优先服务降低平均等待时间的算法。通过朋友圈关系处理,展示了如何计算在考虑友情插队规则下的平均等待时间。

排队“夹塞”是引起大家强烈不满的行为,但是这种现象时常存在。在银行的单窗口排队问题中,假设银行只有1个窗口提供服务,所有顾客按到达时间排成一条长龙。当窗口空闲时,下一位顾客即去该窗口处理事务。此时如果已知第i位顾客与排在后面的第j位顾客是好朋友,并且愿意替朋友办理事务的话,那么第i位顾客的事务处理时间就是自己的事务加朋友的事务所耗时间的总和。在这种情况下,顾客的等待时间就可能被影响。假设所有人到达银行时,若没有空窗口,都会请求排在最前面的朋友帮忙(包括正在窗口接受服务的朋友);当有不止一位朋友请求某位顾客帮忙时,该顾客会根据自己朋友请求的顺序来依次处理事务。试编写程序模拟这种现象,并计算顾客的平均等待时间。

输入格式:

输入的第一行是两个整数:1≤N≤10000,为顾客总数;0≤M≤100,为彼此不相交的朋友圈子个数。若M非0,则此后M行,每行先给出正整数2≤L≤100,代表该圈子里朋友的总数,随后给出该朋友圈里的L位朋友的名字。名字由3个大写英文字母组成,名字间用1个空格分隔。最后N行给出N位顾客的姓名、到达时间T和事务处理时间P(以分钟为单位),之间用1个空格分隔。简单起见,这里假设顾客信息是按照到达时间先后顺序给出的(有并列时间的按照给出顺序排队),并且假设每个事务最多占用窗口服务60分钟(如果超过则按60分钟计算)。

输出格式:

按顾客接受服务的顺序输出顾客名字,每个名字占1行。最后一行输出所有顾客的平均等待时间,保留到小数点后1位。

输入样例:

6 2
3 ANN BOB JOE
2 JIM ZOE
JIM 0 20
BOB 0 15
ANN 0 30
AMY 0 2
ZOE 1 61
JOE 3 10

输出样例:

JIM
ZOE
BOB
ANN
JOE
AMY
75.2

思路 : 插队思想,有朋友的话找到朋友并排在他后面,朋友圈储存可以利用ASCII码创建三维数组,直接记入该人朋友圈,超级方便有没有!还可以节省时间,避免后续超时。

#include<bits/stdc++.h>
using namespace std;

struct Person{
    string name;
    int wechat=0,reach,work; // 朋友圈,抵达时间,办理业务所需时间
};

void Line_Change(int time); // 下一个人抵达时,排队人员发生了变化
void Queue(Person person);  // 入队(包括判断是否能插队)

vector<Person> user;          // 储存用户信息
vector<Person> line;          // 储存排队人员
int pyq[26][26][26] = {0};    // 朋友圈记录,‘A’ 的 ASCII 码为 65,利用该性质直接创建数组记录器
double wait_sum=0,now=0;      // 总等待时间 , 当前时间
int main()
{
    int N,M;
    cin >> N >> M;
    /* 朋友圈数据输入 */
    for(int z=1;z<=M;z++){
        int num;  cin >> num;
        char a[4];
        while (num--){
            cin >> a;
            pyq[a[0]-65][a[1]-65][a[2]-65] = z; // 该人朋友圈记录
        }
    }

    /*  用户信息读入  */
    Person zhangSan;
    for(int z=0;z<N;z++)
    {
        char a[3]; int b[3];
        cin >> a >> zhangSan.reach >> zhangSan.work;
        if(zhangSan.work>60) zhangSan.work = 60;
        zhangSan.name=a;
        zhangSan.wechat = pyq[a[0]-65][a[1]-65][a[2]-65]; // 可以直接判断其有无朋友圈
        user.push_back(zhangSan);
    }

    /*  开始排队啦  */
    for(int z=0;z<N;z++)
    {
        zhangSan = user[z];
        int time = zhangSan.reach - now;
        now += time;
        if(time>0) Line_Change(time);
        Queue(zhangSan);
    }

    /*  人都已经全部过来的,只需清空还在排队的人  */
    while (!line.empty())
    {
        cout << line.front().name << endl;
        wait_sum += (line.size()-1) * line.front().work; // 记入后面等待人的总等待时间
        line.erase(line.begin());
    }

    printf("%.1f",wait_sum*1.0/N); // 平均等待时间 = sum / 总人数
    return 0;
}

void Queue(Person person) {
    if(line.size()<2 || person.wechat==0 || person.wechat==line.back().wechat) // 队伍只有不到俩人,或者该人没有朋友圈,或者该人朋友圈跟最后的一个人刚好相等
    {
        line.push_back(person);
        return;
    }
    for(int z=line.size()-2;z>=0;z--)  // 找到排在最后面朋友的位置并排在他后面(如果该人有朋友的话)
    {
        if(person.wechat == line[z].wechat)
        {
            line.insert(line.begin()+z+1,person); // 插队
            return;
        }
    }
    line.push_back(person);     // 该人没有朋友,排在最后面
}

void Line_Change(int time) {
    while (!line.empty() && time>0)  //有人在排队,并且经过的时间差大于0
    {
        if(line.front().work >= time){  // 该人办理的时间大于等于时间差,之所以等于是因为考虑该人刚好办理完成时,他朋友恰好也来了的情况
            line.front().work -= time;  // 该人还需办理的时间 - time
            wait_sum += (line.size()-1) * time;  // 总等待时间 = time * 等待人数
            time = 0;
        }else{  // 该人办理所需时间小于 time
            wait_sum += (line.size()-1) * line.front().work;
            time -= line.front().work;
            cout << line.front().name << endl; // 该人业务办理完成,输出名字
            line.erase(line.begin());
        }
    }
}

刚学C++ 一个多月,新手上路 ~~~~如有错误请见谅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三块不一样的石头

十分满意,一分打赏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值