银行排队模拟

【问题描述】

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

生产者-消费者(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,其它类推。

#include <stdio.h>
#include <stdlib.h>

struct customer
{
	int num_seq;
	int len_wait;
	struct customer *next;
};
struct customer *cust_queue_front = NULL, *cust_queue_rear = NULL;
int num_window = 3;
int lenlist[1000];

void enqueue(int seq)
{ // put a new customer at the rear of the queue
	struct customer *new_rear = (struct customer *)malloc(sizeof(struct customer));
	new_rear->len_wait = 0;
	new_rear->num_seq = seq;
	new_rear->next = NULL;
	if (cust_queue_front == NULL)
		cust_queue_front = new_rear;
	else 
		cust_queue_rear->next = new_rear;
	cust_queue_rear = new_rear;
}

void dequeue()
{ // delete a customer at the front of the queue
	if (cust_queue_front == NULL)
	{
		printf("ERROR: empty queue.");
	}
	else 
	{
		struct customer *p = cust_queue_front;
		cust_queue_front = cust_queue_front->next;
		free(p);
	}
}

void start_cycle(int num_newcust, int *num_seq)
{// when a cycle starts, enqueue the customers
	int i;
	for (i = 0; i < num_newcust; i++)
	{
		enqueue(*num_seq);
		(*num_seq)++;
	}
 // count the average number for each window, if more than 7:
 // if adding one window can suffice, add one (at most 5 windows altogether)
 // if adding one is not enough, add two (at most 5 windows altogether)
	int len_queue;
	if (cust_queue_front != NULL) len_queue = cust_queue_rear->num_seq - cust_queue_front->num_seq + 1;
	else len_queue = 0;
	if (len_queue / num_window >= 7)
	{
		if (len_queue / (num_window + 1) < 7)
		{
			if(num_window <= 4) (num_window)++;
		}
		else 
		{
			num_window = 5;
		}
	}
}

void finish_cycle()
{// when a cycle is finished, the number of windows equals the number of customers who have received service 
 // thus customers by this number are to be dequeued
	int i;
	for (i = 0; i < num_window; i++)
	{
		if (cust_queue_front != NULL)
		{
			lenlist[cust_queue_front->num_seq - 1] = cust_queue_front->len_wait;
			dequeue();
		}
	}
 // after the customers leave, those staying in the queue have one more unit time for waiting
	struct customer *current = cust_queue_front;
	if (cust_queue_front != NULL)
	{
		for (;;)
		{
			current->len_wait++;
			if (current == cust_queue_rear) break;
			else current = current->next;
		}
	}
 // count the average number for each window, if less than 7, and now more than 3 windows are on, close one of them
	int len_queue;
	if (cust_queue_front != NULL) len_queue = cust_queue_rear->num_seq - cust_queue_front->num_seq + 1;
	else len_queue = 0;
	if ( len_queue / (num_window) < 7 && num_window > 3) num_window--;
}

int main()
{
	int num_cycle, num_newcust, num_seq = 1, num_cust = 0;
	scanf("%d",&num_cycle);
	for (;;)
	{
		scanf("%d",&num_newcust);
		num_cust += num_newcust;
		start_cycle(num_newcust, &num_seq);
		finish_cycle();
		num_cycle--;
		if (num_cycle == 0)
		{
			while (cust_queue_front != NULL)
				finish_cycle();
			break;
		}
	}
	int i;
	for (i = 0; i < num_cust; i++)
		printf("%d : %d\n",i+1,lenlist[i]);
	return 0;
}



  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值