1.问题描述:假设某银行有四个窗口对外接待客户,从早晨银行开门起不断有客户进入银行。由于每个窗口在某个时刻只能接待一个客户,因此在客户人数众多时需在每个窗口前顺次排队,对于刚进入银行的客户,如果某个窗口的业务员正空闲,则可上前办理业务,反之,若四个窗口均有客户所占,他便会排在人数最少的队伍后面。现在需要编制程序以模拟银行的这种业务活动并计算一天中客户在银行逗留的平均时间。
2.基本要求
(1)初始化(OpenForDay),模拟银行开门时各数据结构的状态。
(2)事件驱动(EventDrived), 对客户到达和离开事件做相应处理。
(3)下班处理(CloseForDay),模拟银行关门时的动作,统计客户平均逗留时间。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#include<math.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status;
#define Qu 4
typedef struct
{
int OccurTime;
int NType;
}Event,ElemType;
typedef struct LNode
{
ElemType data;
LNode *next;
}*Link,*Position;
struct LinkList
{
Link head,tail;
int len;
};
typedef struct
{
int ArrivalTime;
int Duration;
}QElemType;
typedef struct QNode
{
QElemType data;
QNode *next;
}*QueuePtr;
struct LinkQueue
{
QueuePtr front,rear;
};
typedef LinkList EventList;
EventList ev;
Event en;
Event et;
LinkQueue q[Qu];
QElemType customer;
int TotalTime=0,CustomerNum=0;
int CloseTime;
Status InitList(LinkList &L)
{
Link p;
p=(Link)malloc(sizeof(LNode));
if(p)
{
p->next=NULL;
L.head=L.tail=p;
L.len=0;
return OK;
}
else
return ERROR;
}
Status DelFirst(LinkList &L,Link h,Link &q)
{
q=h->next;
if(q)
{
h->next=q->next;
if(!h->next)
L.tail=h;
L.len--;
return OK;
}
else
return FALSE;
}
ElemType GetCurElem(Link p)
{
return p->data;
}
Status ListEmpty(LinkList L)
{
if(L.len)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{
return L.len;
}
Position GetHead(LinkList L)
{
return L.head;
}
Status OrderInsert(LinkList &L,ElemType e,int(*comp)(ElemType,ElemType))
{
Link o,p,q;
q=L.head;
p=q->next;
while(p!=NULL&&comp(p->data,e)<0)
{
q=p;
p=p->next;
}
o=(Link)malloc(sizeof(LNode));
o->data=e;
q->next=o;
o->next=p;
L.len++;
if(!p)
L.tail=o;
return OK;
}
Status InitQueue(LinkQueue &Q)
{
if(!(Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode))))
exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status QueueEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return TRUE;
else
return FALSE;
}
int QueueLength(LinkQueue Q)
{
int i=0;
QueuePtr p;
p=Q.front;
while(Q.rear!=p)
{
i++;
p=p->next;
}
return i;
}
Status GetHead(LinkQueue Q,QElemType &e)
{
QueuePtr p;
if(Q.front==Q.rear)
return ERROR;
p=Q.front->next;
e=p->data;
return OK;
}
Status EnQueue(LinkQueue &Q,QElemType e)
{
QueuePtr p;
if(!(p=(QueuePtr)malloc(sizeof(QNode))))
exit(OVERFLOW);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &Q,QElemType &e)
{
QueuePtr p;
if(Q.front==Q.rear)
return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return OK;
}
int cmp(Event a,Event b)
{
if(a.OccurTime==b.OccurTime)
return 0;
else
return (a.OccurTime-b.OccurTime)/abs(a.OccurTime-b.OccurTime);
}
void OpenForDay()
{
int i;
InitList(ev);
en.OccurTime=0;
en.NType=Qu;
OrderInsert(ev,en,cmp);
for(i=0;i<Qu;++i)
InitQueue(q[i]);
}
void Random(int &d,int &i)
{
d=rand()%30+1;
i=rand()%5+1;
}
int Minimum(LinkQueue Q[])
{
int t[Qu];
int i,k;
for(i=0;i<Qu;i++)
t[i]=QueueLength(Q[i]);
k=0;
for(i=1;i<Qu;i++)
if(t[i]<t[0])
{
t[0]=t[i];
k=i;
}
return k;
}
void CustomerArrived(LinkQueue Q[])
{
QElemType f;
int durtime,intertime,i,j;
++CustomerNum;
Random(durtime,intertime);
et.OccurTime=en.OccurTime+intertime;
et.NType=Qu;
if(et.OccurTime<CloseTime)
OrderInsert(ev,et,cmp);
i=Minimum(q);
f.ArrivalTime=en.OccurTime;
f.Duration=durtime;
EnQueue(q[i],f);
if(QueueLength(q[i])==1)
{
et.OccurTime=en.OccurTime+durtime;
et.NType=i;
OrderInsert(ev,et,cmp);
}
printf("客户%d 到达时间为:%d 窗口:%d \n",CustomerNum,et.OccurTime,i+1);
for(i=0;i<Qu;i++)
{
printf("窗口%d: ",i+1);
for(j=0;j<QueueLength(Q[i]);j++)
printf("♀");
printf("\n");
}
}
void CustomerDeparture()
{
int i;
i=en.NType;
DeQueue(q[i],customer);
TotalTime+=en.OccurTime-customer.ArrivalTime;
if(!QueueEmpty(q[i]))
{
GetHead(q[i],customer);
et.OccurTime=en.OccurTime+customer.Duration;
et.NType=i;
OrderInsert(ev,et,cmp);
}
}
void Bank_Simulation()
{
Link p;
OpenForDay();
while(!ListEmpty(ev))
{
DelFirst(ev,GetHead(ev),p);
en.OccurTime=GetCurElem(p).OccurTime;
en.NType=GetCurElem(p).NType;
if(en.NType==Qu)
CustomerArrived(q);
else
CustomerDeparture();
}
printf(" 顾客总数:%d, 所有顾客共耗时 :%d分,平均每人耗时 %d 分钟\n",CustomerNum,TotalTime,TotalTime/CustomerNum);
}
void main()
{
printf("假设客户办理业务时间为1到30分钟,每1到5分钟到来一个客户\n");
printf("输入营业时间(分钟)\n");
scanf("%d",&CloseTime);
Bank_Simulation();
}