先感谢有人给我水东西的机会,好久之前写的东西,内容都忘记了,刚好这几天考试,考完又花了点时间重看了一遍自己写的东西才想起来。
分析:这里相当于在前一个问题两个B取款机的前提下加入了容量k,也就需要判断容量是否满了。
这是包含检测的程序。
%{
银行计划安置取款机, A 机价格和平均服务率都是 B 机的 2倍.。应购置 1 台 A 机还是 2 台 B 机?
顾客平均每分钟到达 1 位, A 型机的平均服务时间为 0.9, B型机为 1.8 分钟, 顾客到达间隔和服务时间都服从指数分布。
%}
people_num=100;%设置访问人数
at=1;ft=0.9;%到达和服务的指数分布参数
k=2;%设置等待容量
kw=0;%等待人数
%两台B机器
ft_b=1.8;
ft_dis_b=exprnd(ft_b,1,people_num);
ser_time_b=zeros(people_num,1);%新建服务时刻数组
lea_time_b=zeros(people_num,1);%新建离开时刻数组
wai_time_b=zeros(people_num,1);%新建等待时长数组
cou=[0 0];%初始柜台
ser_time_b(1)=at_dis(1);%第一个客户出现
lea_time_b(1)=at_dis(1)+ft_dis(1);%第一个客户结束服务——离开时刻
wai_time_b(1)=0;%等待时长
cou(1)=lea_time(1);
i=2;
wait_num=0;
for i=2:people_num
if at_dis(i)>= ser_time_b(i-1) && wait_num==1 %顾客到时,前一个等待顾客开始服务了
send_m='前一个等待顾客开始服务'
send_m='该客户序号'
send=i
send_m='该客户到达时刻'
send=at_dis(i)
send_m='前一个客户服务开始时刻'
send=ser_time_b(i-1)
kw=kw-1
wait_num=0;
end
if kw==k && at_dis(i)>= ser_time_b(i-2)
kw=kw-1
end
if kw>=k
send=i
send_m='人满了'
send_m='该客户服务时刻与结束时刻'
ser_time_b(i)=ser_time_b(i-1);
lea_time_b(i)=ser_time_b(i);
send=ser_time_b(i)
send=lea_time_b(i)
end
if kw < k%容量未满
[mi w]=min(cou);%选择最早结束的机器
ser_time_b(i)=max(at_dis(i),cou(w));%可以开始服务时刻
if ser_time_b(i) > at_dis(i)%顾客到时,没有机器空闲,要等待
send_m='需要等待'
send_m='该客户序号'
send=i
send_m='该客户到达时刻'
send=at_dis(i)
send_m='客户可以进行服务时刻'
send=ser_time_b(i)
kw=kw+1
wait_num=1;
end
if (mi <= at_dis(i))||(kw<=k)%机器空闲,或容量没满,算进服务时长
lea_time_b(i)=ser_time(i)+ft_dis_b(i);%离开时刻
cou(w)=lea_time_b(i);
wai_time_b(i)=at_dis(i)-cou(w);%等待时长
end
end
send_m='结束一次循环'
end
xx=[1:1:people_num];
plot(xx,ft_dis_b,xx,ser_time_b);
legend('到达时间','服务时间');
思路
由于有容量,当等待人数kw大于k的时候,来的人会直接走,就不需要计算他的服务时间,但是在他到达的时间点上,是需要查看等待人数是否要改变的。
一个大循环,对于每一个到达的顾客进行分析
for i=2:people_num
第四个顾客开始,会存在前一个等待的顾客是否在他到来时开始服务,如果开始了,那么等待服务的人就减少一个。
if at_dis(i)>= ser_time_b(i-1) && wait_num==1 %顾客到时,前一个等待顾客开始服务了
send_m='前一个等待顾客开始服务'
send_m='该客户序号'
send=i
send_m='该客户到达时刻'
send=at_dis(i)
send_m='前一个客户服务开始时刻'
send=ser_time_b(i-1)
kw=kw-1
wait_num=0;
end
先判断是否满了,这个顺序不能和后面容量未满部分互换因为容量未满可能出现新来的人加入等待序列。如果后判断是否人满会把等待客户的服务时刻和离开时刻覆盖成前一个客户的离开时刻。
if kw>=k
send=i
send_m='人满了'
send_m='该客户服务时刻与结束时刻'
ser_time_b(i)=ser_time_b(i-1);
lea_time_b(i)=ser_time_b(i);
send=ser_time_b(i)
send=lea_time_b(i)
end
在容量未满的时候,等待的顾客会排出他们的服务时刻,当容量满的时候,这一步骤跳过,因此在跳过顾客的服务时刻变成了0,可以在跳过时赋值来保证绘图时的观测效果更好
if kw < k%容量未满
[mi w]=min(cou);%选择最早结束的机器
ser_time_b(i)=max(at_dis(i),cou(w));%可以开始服务时刻
if ser_time_b(i) > at_dis(i)%顾客到时,没有机器空闲,要等待
send_m='需要等待'
send_m='该客户序号'
send=i
send_m='该客户到达时刻'
send=at_dis(i)
send_m='客户可以进行服务时刻'
send=ser_time_b(i)
kw=kw+1
wait_num=1;
end
if (mi <= at_dis(i))||(kw<=k)%机器空闲,或容量没满,算进服务时长
lea_time_b(i)=ser_time(i)+ft_dis_b(i);%离开时刻
cou(w)=lea_time_b(i);
wai_time_b(i)=at_dis(i)-cou(w);%等待时长
end
end
不管跳不跳过,循环一次后下一个客户的编号必然加一
i=i+1;
证明一次结束
send_m='结束一次循环'
绘制图
plot(xx,ft_dis_b,xx,ser_time_b);
legend('到达时间','服务时间');
效果
图中我标注的96和98点是为验证点出的
可以看到96后有水平服务时刻,就是说97开始时人满状态。我们可以根据命令行窗口查看是否输出了对应的语句。
可以看到96号等待,97-98号因为人满了而离开,所以服务时刻不变是水平的,99号和100号正常服务。99号进行了等待。
21-11-17日修改
有同学发现了代码出现了一种bug,如果等待队列中已经存在两人,而在第三个人到达的时候,等待队列的第一个人已经进入服务,这时,新来的人应该加入等待队列。但源代码中没有考虑到这一情况,导致第三个人会被跳过。
解决:再额外添加一组if语句,单独判断当队列人数为2时,新来的人到达后,队列里的第一个人是否已经进入服务,如果进入服务,他到达时,实际的等待人数为1,这样就可以按照后续队列未满的情况继续计算。