PTA 银行排队问题之单队列多窗口加VIP服务 队列+模拟

Posted fan-jiaming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PTA 银行排队问题之单队列多窗口加VIP服务 队列+模拟相关的知识,希望对你有一定的参考价值。

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

有些银行会给VIP客户以各种优惠服务,例如专门开辟VIP窗口。为了最大限度地利用资源,VIP窗口的服务机制定义为:当队列中没有VIP客户时,该窗口为普通顾客服务;当该窗口空闲并且队列中有VIP客户在等待时,排在最前面的VIP客户享受该窗口的服务。同时,当轮到某VIP客户出列时,若VIP窗口非空,该客户可以选择空闲的普通窗口;否则一定选择VIP窗口。

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

输入格式:

输入第1行给出正整数N(≤),为顾客总人数;随后N行,每行给出一位顾客的到达时间T、事务处理时间P和是否VIP的标志(1是VIP,0则不是),并且假设输入数据已经按到达时间先后排好了顺序;最后一行给出正整数K(≤)—— 为开设的营业窗口数,以及VIP窗口的编号(从0到K1)。这里假设每位顾客事务被处理的最长时间为60分钟。

输出格式:

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

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

输入样例:

10
0 20 0
0 20 0
1 68 1
1 12 1
2 15 0
2 10 0
3 15 1
10 12 1
30 15 0
62 5 1
3 1

输出样例:

15.1 35 67
4 5 1

调了整整一下午,真的恶心,注意看清加粗字体的要求,用队列模拟就行了,因为之前用结构体写过好几次队列了,这次就偷懒直接用STL里的了,代码如下(因为网上代码多是用时间流逝模拟,所以贴出我的代码以供交流学习,还望不要抄袭作业,毕竟可能会查重的:
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <queue>
  6 
  7 using namespace std;
  8 
  9 #define INF 0x3f3f3f3f
 10 
 11 const int maxn = 1000 + 5;
 12 
 13 struct people {
 14     int T, P, VIP, counter_id;
 15 }Customer[maxn];
 16 
 17 int main()
 18 {
 19     int n;
 20     scanf("%d", &n);
 21     for(int i = 0; i < n; ++i) {
 22         scanf("%d %d %d", &Customer[i].T, &Customer[i].P, &Customer[i].VIP);
 23         Customer[i].P = min(Customer[i].P, 60);
 24     }
 25 
 26     int K, vipK;
 27     scanf("%d %d", &K, &vipK);
 28 
 29     bool vis[maxn] = {0};
 30 
 31     queue<people> q;
 32 
 33     bool ok = true;
 34 
 35     for(int i = 0; i < n; ++i) {
 36         if(Customer[i].T > 0)
 37             break;
 38         if(Customer[i].VIP) {
 39             ok = false;
 40             Customer[i].counter_id = vipK;
 41             vis[i] = 1;
 42             q.push(Customer[i]);
 43             break;
 44         }
 45     }
 46 
 47     if(ok) {
 48         Customer[0].counter_id = 0;
 49         vis[0] = 1;
 50         q.push(Customer[0]);
 51     }
 52 
 53     int sum = 0, _max = 0, last = 0, now = 0;
 54     int windows[15] = {0}, num_windows[15] = {0};
 55 
 56     while(!q.empty()) {
 57         _max = max(_max, windows[q.front().counter_id] - q.front().T);
 58         sum += max(0, windows[q.front().counter_id] - q.front().T);
 59         windows[q.front().counter_id] = max(windows[q.front().counter_id], q.front().T) + q.front().P;
 60         last = max(last, windows[q.front().counter_id]);
 61         ++num_windows[q.front().counter_id];
 62 
 63         int minn = INF, idx = 0;
 64 
 65         for(int i = 0; i < K; ++i) {
 66             if(windows[i] < minn) {
 67                 minn = windows[i];
 68                 idx = i;
 69             }
 70         }
 71 
 72         while(now < n && vis[now])
 73             ++now;
 74         if(now == n)
 75             break;
 76 
 77         ok = true;
 78 
 79         if(Customer[now].T <= windows[idx]) {
 80             ok = true;
 81             if(idx == vipK || windows[idx] == windows[vipK]) {
 82                 for(int i = now; i < n; ++i) {
 83                     if(!vis[i]) {
 84                         if(Customer[i].T > windows[idx]) {
 85                             break;
 86                         }
 87                         if(Customer[i].VIP) {
 88                             ok = false;
 89                             Customer[i].counter_id = vipK;
 90                             q.push(Customer[i]);
 91                             vis[i] = 1;
 92                             break;
 93                         }
 94                     }
 95                 }
 96             }
 97             if(ok) {
 98                 Customer[now].counter_id = idx;
 99                 q.push(Customer[now]);
100                 vis[now] = 1;
101             }
102         }
103         else {
104             if(Customer[now].VIP && windows[vipK] <= Customer[now].T) {
105                 Customer[now].counter_id = vipK;
106                 q.push(Customer[now]);
107                 vis[now] = 1;
108             }
109             else {
110                 for(int i = 0; i < K; ++i) {
111                     if(windows[i] <= Customer[now].T) {
112                         Customer[now].counter_id = i;
113                         q.push(Customer[now]);
114                         vis[now] = 1;
115                         break;
116                     }
117                 }
118             }
119         }
120         q.pop();
121     }
122 
123     printf("%.1f %d %d
", sum * 1.0 / n, _max, last);
124 
125     for(int i = 0; i < K; ++i) {
126         printf("%d%c", num_windows[i], i == K - 1 ? 
 :  );
127     }
128 
129     return 0;
130 }

 

以上是关于PTA 银行排队问题之单队列多窗口加VIP服务 队列+模拟的主要内容,如果未能解决你的问题,请参考以下文章

用队列管理解决食客的排队问题

博客作业03--栈和队列

银行VIP插队引不满,为何银行八个窗口只开一个?

7-48 银行排队问题之单窗口“夹塞”版 (30分)--map,vector

怎么样才能去银行不用排队直接走VIP通道呢?都有哪些方法?

为啥不管多少客户在排队银行总是一两个窗口办业务?