任务
银行客户业务分为两种:第一种是申请从银行得到一笔资金,即取款或借款;第二种是向银行投入一笔资金,即存款或还款。
银行有两个服务窗口,相应地有两个队列。客户到达银行后先排第一个队,处理每个客户业务时,如果属于第一种,且申请额超出银行现存资金总额而得不到满足,则立刻排入第二个队等候直至满足时才离开银行;否则业务处理完后立刻离开银行,每接待完一个第二种业务的客户,则顺序检查和处理(如果可能)第二个队列中的客户,对能满足的申请者予以满足,不能满足者重新排到第二个队列的队尾。注意,在此检查过程中,一旦银行资金总额少于或等于刚才第一个队列中最后一个客户(第二种业务)被接待之前的数额,或者本次已将第二个队列 检查或处理了一遍,就停止检查(因为此时已不可能还有能满足者),转而继续接待第一个队列的客户。任何时刻都只开一个窗口。假设检查不需要时间,营业时间结束时所有客户立即离开银行。
写一个上述银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。
输入格式
第一行输入四个数 N、total、close_time、average_time,分别表示来银行的总人数、银行开始营业时拥有的款额、今天预计的营业时长和客户交易时长,之后的 N 行每行输入两个数 a、b,第一个数 a 为客户办理的款额,用负值和正值分别表示第一类和第二类业务。第二个数 b 为客户来到银行的时间。
输出格式
前 N 行输出分别对应每个客户的等候时长
第 N+1 行输出为客户等候平均时长,结果去尾法保留整数即可
输入样例
4 10000 600 10
-2000 0
-11000 10
-10000 30
2000 50
输出样例
第1个顾客的等待时间为0
第2个顾客的等待时间为590
第3个顾客的等待时间为30
第4个顾客的等待时间为0
4个顾客的平均等待时间为155
样例解释
开始时银行有存款 10000 元,顾客交易时长 10
1号顾客0时刻到达银行,于 10 时办理完手续离开,此时银行有款额8000元;
2号顾客10时刻到达银行,此时银行内存款不足,进入队列 2;
3号顾客30时刻到达银行,此时银行内存款不足,进入队列 2;
4号顾客50时刻到达银行,于60时办理完手续离开,此时银行有款额10000元。
这时扫描队列2,队列2中第一个顾客2号顾客的要求仍然不满足,2 号顾客出队再入队;此时队列 2 中第一个顾客3号客户满足要求,因此3号顾客于60时刻开始办理手续,于70时刻办理完毕离开银行,等待时间为60-30=30,此时银行有余款 0 元。
然后直到银行营业时间 600时刻之前2号客户都没有离开银行,等待时间为600-10=590。
源代码
队列相关操作
#include<iostream>
using namespace std;
typedef struct QueueList{
int num; //顾客序号
struct QueueList* next;
}Queue;
Queue* EnQueue(Queue** Q,int n){//将顾客进队
Queue *p=(Queue*)malloc(sizeof(Queue));
if(!p){
printf("申请空间失败");
return NULL;
}
p->num=n;
if(!*Q){
*Q=p;
(*Q)->next=NULL;
}
else{
Queue* q=*Q;
while(q->next)
q=q->next;
q->next=p;
p->next=NULL;
}
return *Q;
}
int DeQueue(Queue** Q){//将队首顾客出队
if(!*Q)
return -1;
int i;
Queue *p=*Q;
i=p->num;
*Q=(*Q)->next;
free(p);
return i;
}
模拟过程
int main(){
int n,i,arrive[50]={0},status[50],Time=0,wait[50]={0},waittotal=0,waitaverage=0,closetime=0,avetime=0,Money=0,money[50]={0},moneytemp=0;
//n为顾客人数,arrive数组记录每个顾客来到银行的时间,status数组记录每个顾客的状态,-1为未来银行,0为正在等待,1为已离开
//Time表示当前时间,wait数组记录每个顾客等待的时间,waittotal是所有顾客等待的总时间,waitaverage是顾客等待的平均时间,closetime是银行关门时间,avetime是每笔交易的平均时间
//Money为银行一开始的款额,money数组记录每个顾客的交易金额,正数为存钱,负数为取钱,moneytemp用来记录第一个队列最后一个客户(第二种业务)接待前银行的剩余款额
cout<<"请依次输入顾客总人数、银行开始营业时拥有的款额、今天预计的营业时长和客户交易时长"<<endl;
cin>>n>>Money>>closetime>>avetime;
Queue* Q=NULL;
cout<<"请依次输入每个顾客要交易的款额(用负值和正值分别表示第一类和第二类业务)和客户来到银行的时间"<<endl;
for(i=0;i<n;i++){
cin>>money[i]>>arrive[i];
status[i]=-1;
}
for(i=0;i<n;i++){
if (arrive[i]>=closetime-avetime) {//在关门前完成不了交易相当于一直等到关门
status[i]=0;
break;
}
else {
if(Time<arrive[i])
Time=arrive[i];//重置当前时间
if(money[i]<0){//第一种业务:取钱
if(-money[i]<=Money){//银行有足够余额
Money+=money[i];
wait[i]=Time-arrive[i];
status[i]=1;
Time+=avetime;//重置当前时间
moneytemp=Money;
if(Time>=closetime)
loop:break;
}
else{//银行没有足够余额,进入第二条队等待
status[i]=0;
EnQueue(&Q,i);
}
}
else{//第二种业务
Money+=money[i];
wait[i]=Time-arrive[i];
status[i]=1;
Time+=avetime;//重置当前时间
int status2[50]={0};//用来标记第二条队的顾客是否被检查到,没检查是0,检查到是1
while (Money>moneytemp){
Money+=money[i];
wait[i]=Time-arrive[i];
status[i]=1;
Time+=avetime;//重置当前时间
int status2[50]={0};//用来标记第二条队的顾客是否被检查到,没检查是0,检查到是1
while (Money>moneytemp){
int k=DeQueue(&Q);
if(k==-1) break;
else if(!status2[k]){
if(-money[k]<=Money){
Money+=money[k];
wait[k]=Time-arrive[k];
status[k]=1;
Time+=avetime;//重置当前时间
moneytemp=Money;
if(Time>=closetime)
goto loop;//跳出while循环和for循环
}
else{
status2[i]=1;
EnQueue(&Q,i);//不满足就重新入队
}
}
}
}
}
}
for ( i = 0; i < n; i++){
if(!status[i])
wait[i]=closetime-arrive[i];
cout<<"第"<<i+1<<"个顾客的等待时间为"<<wait[i]<<endl;
}
for ( i = 0; i < n; i++)
waittotal+=wait[i];
waitaverage=waittotal/n;
cout<<n<<"个顾客的平均等待时间为"<<waitaverage<<endl;
return 0;
}