7-1 银行排队问题之单队列多窗口服务 分数 25

假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙。当有窗口空闲时,下一位顾客即去该窗口处理事务。当有多个窗口可选择时,假设顾客总是选择编号最小的窗口。

本题要求输出前来等待服务的N位顾客的平均等待时间、最长等待时间、最后完成时间,并且统计每个窗口服务了多少名顾客。

输入格式:

输入第1行给出正整数N(≤1000),为顾客总人数;随后N行,每行给出一位顾客的到达时间T和事务处理时间P,并且假设输入数据已经按到达时间先后排好了顺序;最后一行给出正整数K(≤10),为开设的营业窗口数。这里假设每位顾客事务被处理的最长时间为60分钟。

输出格式:

在第一行中输出平均等待时间(输出到小数点后1位)、最长等待时间、最后完成时间,之间用1个空格分隔,行末不能有多余空格。

在第二行中按编号递增顺序输出每个窗口服务了多少名顾客,数字之间用1个空格分隔,行末不能有多余空格。

输入样例:

9
0 20
1 15
1 61
2 10
10 5
10 3
30 18
31 25
31 2
3

输出样例:

6.2 17 61
5 3 1

具体实现看代码注释,当一个人面临很多个窗口的wintime比他到达的时间少时,把这些窗口的wintime改成他到达的时间,这样在优先队列中会优先选择编号最小的。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
using namespace std;
const int maxn = 105000;
int wintime[15] = {};//记录各窗口服务完客户后的时间,初始化为0
struct Guest{
    int T;//到达时间
    int P;//事务处理时间
}temp[maxn];//客户结构体
struct window{
    int index;//编号
    int count;//记录服务客户数量
}win[maxn];//窗口结构体
struct compare{
    bool operator()(const int &x,const int &y) const {
        if(wintime[x] != wintime[y]) return wintime[x] > wintime[y];//返回服务完客户后时间小的窗口
        return x > y;//返回编号小的窗口
        // if(wintime[x] == wintime[y]) return x > y;//返回编号小的窗口
        // else return wintime[x] > wintime[y];//返回服务完客户后时间小的窗口
    }
};//优先队列自定义优先规则,规定时间少窗户优先和编号小窗户优先
int main()
{
    int N,K;
    priority_queue<int,vector<int>,compare>Q;//优先队列Q
    cin>>N;
    int endtime = 0,maxtime = 0,waittime = 0;//定义最后完成时间、最长等待时间、等待时间的和
    for(int i = 0;i < N;i++){//输入每一位客户的到达时间和处理时间  
        cin>>temp[i].T;
        cin>>temp[i].P;
        if(temp[i].P > 60) temp[i].P = 60;
    }
    cin>>K;
    for(int i = 0;i < K;i++){//输入每一个窗口的编号、计数,把他们都入队
        win[i].index = i;
        win[i].count = 0;
        Q.push(i);
    }
    for(int i = 0;i < N;i++){//大循环,求出等待时间的和、最长等待时间、最后完成时间
        while(wintime[Q.top()] < temp[i].T){//这个while,当一个人面临很多个窗口的wintime比他到达的时间少时,把这些窗口的wintime改成他到达的时间,这样在优先队列中会优先选择编号最小的。
            int ww = Q.top();
            Q.pop();
            wintime[ww] = temp[i].T;
            Q.push(ww);
        }
        int ww = Q.top();//最优先的窗口出队
        Q.pop();
        win[ww].count++;//窗口计数
        if(wintime[ww] > temp[i].T){//如果ww号窗口的wintime大于一个人的到达时间,那么这个人就需要等待
            waittime += wintime[ww] - temp[i].T;//计算这个人的等待时间=窗口服务完客户后的时间-到达时间
            maxtime = max(maxtime,wintime[ww] - temp[i].T);//实时更新最长等待时间
        }
        wintime[ww] = max(wintime[ww],temp[i].T) + temp[i].P;//针对不需要等待的人,wintime就为到达时间+处理时间,max选择了wintime[ww]是这个人刚好不需要排队的情况
        endtime = max(endtime,wintime[ww]);//实时更新最后完成时间
        Q.push(ww);//窗口入队
    }
    printf("%.1f %d %d\n",waittime*1.0/N,maxtime,endtime);//输出平均等待时间、最后完成时间、最长等待时间。
    for(int i = 0;i < K;i++){//输出每个窗口服务客户的数目
        if(i) printf(" ");
        cout<<win[i].count;
    }
    printf("\n");
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值