BUAA_数据结构_4TH_银行排队模拟(生产者-消费者模拟)

BUAA_数据结构_4TH_银行排队模拟(生产者-消费者模拟)

题目描述:

一个系统模仿另一个系统行为的技术称为模拟,如飞行模拟器。模拟可以用来进行方案论证、人员培训和改进服务。计算机技术常用于模拟系统中。
生产者-消费者(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),以此类推。

输出形式

每个客户等待服务的时间周期数。输出形式如下:
用户序号 : 等待周期数
说明:客户序号与等待周期数之间用符号:分隔,冒号(:)两边各有一个空格,等待周期数后直接为回车。

参考代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define maxN 100
struct customer{
    int id;
    int wait_time;
};
typedef struct customer customer;
int windows_num=3;
int front,rear,count;
customer queue[maxN];

void initQueue();
int is_full();
int is_empty();
void enter_queue(customer x);
customer outer_queue();
int get_queue_num();

void update_wait_time();
void arrive_customer();
int service();

int main()
{
    initQueue();
    int n;
    scanf("%d",&n);
    for(int clock=1;;clock++){
        update_wait_time();
        if(clock<=n){
            arrive_customer();
        }
        if(service()==0 && clock > n){
            break;
        }
    }
    return 0;
}

void initQueue()
{
    front=0;
    rear=maxN-1;
    count=0;
}

int is_full()
{
    return count==maxN;
}

int is_empty()
{
    return count==0;
}

void enter_queue(customer x)
{
    if(is_full()){
        printf("Full!!!");
    }
    else{
        rear=(rear+1)%maxN;
        queue[rear]=x;
        count++;
    }
}

customer outer_queue()
{
    customer res;
    if(is_empty()){
        printf("EMPTY!!!");
    }
    else{
        res=queue[front];
        count--;
        front=(front+1)%maxN;
        return res;
    }
}

int get_queue_num()
{
    return count;
}

void update_wait_time()
{
    for(int i=front;i<=rear;i++){
        queue[i].wait_time++;
    }
}

void arrive_customer()
{
    static count_compute=1;
    customer temp;
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        temp.id=count_compute++;
        temp.wait_time=0;
        enter_queue(temp);
    }
    while((get_queue_num()/windows_num)>=7&&windows_num<5){
        windows_num++;
    }
}

int service()
{
    customer c;
    for(int i=0;i<windows_num;i++){
        if(is_empty()) return 0;
        else{
            c=outer_queue();
            printf("%d : %d\n",c.id,c.wait_time);
        }
    }
    if((get_queue_num()/windows_num)<7&&windows_num>3){
        windows_num--;
    }
    return 1;
}

在这里插入图片描述
说明:客户序号与等待周期数之间用符号:分隔,冒号(:)两边各有一个空格,等待周期数后直接为回车。
第一次提交的时候忘记了冒号两侧的空格… 结果如上图所示
在这里插入图片描述

有问题或bug 欢迎私戳/评论

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值