银行排队问题(详解队列)

这算是我入园的第一篇笔记咯~

PLUS:该代码来自亲学长(下面那个)

 手动@     黑色老鸟

 https://www.cnblogs.com/tuoniao/p/10346452.html

(我只是注释的作者哈)------     (辣鸡三水,在线注释)

【问题描述】

一个系统模仿另一个系统行为的技术称为模拟,如飞行模拟器。模拟可以用来进行方案论证、人员培训和改进服务。计算机技术常用于模拟系统中。

生产者-消费者(Server-Custom)是常见的应用模式,见于银行、食堂、打印机、医院、超等提供服务和使用服务的应用中。这类应用的主要问题是消费者如果等待(排队)时间过长,会引发用户抱怨,影响服务质量;如果提供服务者(服务窗口)过多,将提高运管商成本。(经济学中排队论)

假设某银行网点有五个服务窗口,分别为三个对私、一个对公和一个外币窗口。银行服务的原则是先来先服务。通常对私业务人很多,其它窗口人则较少,可临时改为对私服务。假设当对私窗口等待服务的客户(按实际服务窗口)平均排队人数超过(大于或等于)7人时,等待客户将可能有抱怨,影响服务质量,此时银行可临时将其它窗口中一个或两个改为对私服务,当客户少于7人时,将立即恢复原有业务。设计一个程序用来模拟银行服务。

说明:

1. 增加服务窗口将会增加成本或影响其它业务,因此,以成本增加或影响最小为原则来增加服务窗口,即如果增加一个窗口就能使得按窗口平均等待服务人数小于7人,则只增加一个窗口。一旦按窗口平均等待服务人数小于7人,就减少一个所增加的窗口。

2. 为了简化问题,假设新到客户是在每个服务周期开始时到达。

3. 当等待服务人数发生变化时(新客户到达或有客户已接受服务),则及时计算按实际服务窗口平均等待服务人数,并按相应策略调整服务窗口数(增加或减少额外的服务窗口,但对私窗口不能减少)。注意:只在获取新客户(不管到达新客户数是否为0)时或已有客户去接受服务时,才按策略调整服务窗口数。进一步讲,增加服务窗口只在有客户到达的周期内进行(也就是说增加窗口是基于客户的感受,银行对增加窗口是不情愿的,因为要增加成本,一旦不再有新客户来,银行是不会再增加服务窗口的);一旦有客户去接受服务(即等待客户减少),银行将根据策略及时减少服务窗口,因此,在每个周期内,有客户去接受服务后要马上判断是否减少服务窗口(因为能减少成本,银行是积极的)

 

本问题中假设对公和对外币服务窗口在改为对私服务时及服务期间没有相应因公或外币服务新客户到达(即正好空闲),同时要求以增加成本或影响最小为前提,来尽最大可能减少对私服务客户等待时间。

【输入形式】

首先输入一个整数表示时间周期数,然后再依次输入每个时间周期中因私业务的客户数。注:一个时间周期指的是银行处理一笔业务的平均处理时间,可以是一分钟、三分钟或其它。例如:

6

2  5  13  11  15   9 

 

说明:表明在6个时间周期内,第1个周期来了2个(序号分别为1,2),第2个来了5人(序号分别为3,4,5,6,7),以此类推。

【输出形式】

每个客户等待服务的时间周期数。输出形式如下:

用户序号 : 等待周期数

说明:客户序号与等待周期数之间用符号:分隔,冒号(:)两边各有一个空格,等待周期数后直接为回车。

 

【样例输入】

4

2  5  13  11

 

【样例输出】

1 : 0

2 : 0

3 : 0

4 : 0

5 : 0

6 : 1

7 : 1

8 : 0

9 : 1

10 : 1

11 : 1

12 : 1

13 : 2

14 : 2

15 : 2

16 : 3

17 : 3

18 : 3

19 : 4

20 : 4

21 : 3

22 : 4

23 : 4

24 : 4

25 : 5

26 : 5

27 : 5

28 : 6

29 : 6

30 : 6

31 : 7

 

【样例说明】

样例输入表明有四个时间周期,第一个周期来了2人(序号1-2);第二个周期来了5人(序号3-7);第三个周期来了13人(序号8-20);第四个周期来了11人(序号21-31)。由于第一个时间周期内只来了2人,银行(有三个服务窗口)能及时提供服务,因此客户等待时间为0;第二个时间周期内来了5人,银行一个周期内一次只能服务3人,另有2个在下个周期内服务,因此等待时间为1,其它类推。

【评分标准】

通过所有测试点得满分。


  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 #define MAXSIZE 200//队列里面的总人数
  5 #define MINSVR 3//当银行正常的时候一个时间周期只能服务3个人
  6 #define MAXSVR 5//银行功能全开,最多一个周期服务5个人
  7 #define NUMBER 7//正常服务时的人数最大限
  8 
  9 /*说明:
 10         在生产者-消费者应用中消费者显然是先来先得到服务。在此,显然
 11     可用一个队列来存放等待服务的客户队列。每个客户有二个基本属性:
 12     排队序号和等待时间(时间周期数)
 13     
 14     等待服务的客户队列,一个循环队列
 15     
 16     伪代码核心算法:
 17     
 18     for(clock=1; ; clock++) //在每个时间周期内
 19     {
 20     1. If 客户等待队列非空
 21         将每个客户的等待时间增加一个时间单元;
 22     2. If(clock <= simulationtime)
 23         2.1 如果有新客户到来(从输入中读入本周期内新来客户数),将其入队;
 24         2.2 根据等待服务客户数重新计算服务窗口数;
 25     3. If 客户等待队列非空
 26         3.1 从客户队列中取(出队)相应数目(按实际服务窗口数)客户获得服务;
 27         3.2 然后根据等待服务客户数重新计算服务窗口数;
 28     Else 结束模拟
 29     }
 30 */
 31 /*
 32     理解:
 33         对于排队问题,可以划分为处理元,将所有的数据全部入队,排成线性结构
 34         然后按照银行的处理能力(处理元)依次出队,此间每经历一次周期就更新
 35         一次数据,并且相应地对客户的等待时间进行增加处理
 36 */
 37 
 38 ///所以对于排队现状的更新是按照时间周期来的///
 39 //定义结构,对于每一个客户,id代表其编号,wait_time表示其等待时间
 40 typedef struct
 41 {
 42     int id;
 43     int wait_time;
 44 }Cust;
 45 
 46 //设立队列
 47 Cust queue[MAXSIZE];
 48 
 49 int front = 0,real = -1,people_count = 0;
 50 //people_count为队列中的人数,是判断队列是否为空的指标
 51 
 52 
 53 int normal_sev_time = MINSVR;//正常的工作时间
 54 
 55 ///---------函数------------///
 56 //int isEmpty();            ///
 57 //int isFull();             ///
 58 //void enQueue(Cust q);    ///
 59 //Cust deQueue();          ///
 60 //void updatetime();        ///
 61 //void arriveCust();        ///
 62 //void service();           ///
 63 ///-------------------------///
 64 
 65 //判断队列是否为空
 66 int isEmpty()
 67 {
 68     return people_count == 0;
 69 }
 70 
 71 
 72 //判断队列是否满员
 73 int isFull()
 74 {
 75     return people_count == MAXSIZE;
 76 }
 77 
 78 
 79 //将q元素进入队列
 80 void enQueue(Cust q)
 81 {
 82 
 83     if(isFull())
 84         exit(-1);
 85         
 86     else
 87     {
 88         //数据周期覆盖
 89         real=(real+1)%MAXSIZE;
 90         queue[real]=q;
 91         //人数++
 92         people_count++;
 93     }
 94     return;
 95 }
 96 
 97 
 98 //出队,同时取出队首元素q
 99 Cust deQueue()
100 {
101     Cust q;
102     //判断队列是否为空
103     if(isEmpty())
104         exit(-1);
105         
106     else
107     {
108         //开始时front == 0,代表队首
109         q=queue[front];
110         //队首指针向后移动
111         front=(front+1)%MAXSIZE;
112         
113         //人数--
114         people_count--;
115     }
116     return q;
117 }
118 
119 
120 //对所有的客户的等待时间进行更新
121 void updatetime()
122 {
123     int i;
124     for(i=0;i<people_count;i++)
125         queue[(front+i) % MAXSIZE].wait_time++;
126         //front表示从队首开始,从头开始每位客户的候时加一
127     return;
128 }
129 
130 
131 
132 //对于新到来的客户的入队或者开启备用窗口操作
133 void arriveCust()
134 {
135     //静态局部变量
136     static int count=1;
137     int i,n;
138     
139     Cust q;
140     //读入该个时间周期里面的客户数量
141     scanf("%d",&n);
142     
143     //更改每个客户的id号,并入队
144     for(i=0;i<n;i++)
145     {
146         q.id = count++;//id号码更改
147         q.wait_time=0;//客户候时初始化
148         enQueue(q);
149     }
150     
151     //核心
152     while((people_count/normal_sev_time) >= NUMBER && normal_sev_time < MAXSVR)
153         //根据需求开始加窗口,但是不可以超过5
154         normal_sev_time++;
155         
156     return;
157 }
158 
159 
160 
161 
162 void service()
163 {
164     int i;
165     Cust q;
166     
167     //每次出队相应的人数(窗口数)
168     for(i=0;i < normal_sev_time;i++)
169     {
170         //如果队列里面为空就直接返回
171         if(isEmpty())
172             return;
173             
174         else
175         {
176             q=deQueue();
177             printf("%d : %d\n",q.id,q.wait_time);
178         }
179     }
180         
181     //出队时实时更新关闭多余的窗口
182     while((people_count/normal_sev_time) < NUMBER && normal_sev_time > MINSVR)
183         normal_sev_time--;
184         
185     return;
186 }
187 
188 int main()
189 {
190     int clock,loop;
191     
192     //周期数
193     scanf("%d",&loop);
194     
195     clock=1;
196     while(1)
197     {
198         //如果队列显示不为空,实时更新候时
199         if(!isEmpty())
200             updatetime();
201             
202         //读入一次客户
203         if(clock <= loop)
204             arriveCust();
205             
206         //处理
207         service();
208         
209         
210         if(people_count == 0 && clock > loop)
211             break;
212             
213         
214         clock++;
215     }
216     return 0;
217 }

 


 

posted @ 2019-04-06 23:29  samshui  阅读(5140)  评论(3编辑  收藏  举报