[计算机模拟]经典报童问题
By EmilMatthew
06/03/31
1问题的提出:
经典的报童问题可描述如下:
一报童从报刊发行处订报后零售,每卖出一分可获利a元,若订报后卖不出去,则退回发行处,每分将要赔钱b元.问:报童如何根据以往的卖报情况(每天卖出k份的概率pk)来推算出每天收益达到最大的订报量Z*.
2思考:
要使每天收益达到最大,也就是要使每天的亏损达到最小,考虑供过于求和供不于求的两种情况.
设报童每天订报z份,而报纸每天卖出y份,则y应有分布列:
P(y=k)=pk k=0,1,2…,
a) 供过于求时,则退货期望数E(x1)=sigma((z-k)*pk) (0=<k<=z),平均损失为c1=b*E(x1).
b) 供不应求时,则缺货数量的期望值为:E(x2)=sigma((k-z)*pk) (k>=z+1),平均损失为:
c2=a*E(x2)
有了以上分析,再加上适当的随机数生成,可以采用多次模拟,每次摸拟若干天,求出平均损失.再取其中的较小值即可.
3摸拟程序设计:
MinKuiVal=MaxData;//最小亏损额
Z=0;//摸拟的次数
While(Z<ZMax)
{
T=0;//每次摸拟的天数累计
SCount=0;//每次摸拟的总亏损量累计
SAvg=0;// 每次摸拟的平均亏损量
While(T<StimDays)
{
根据正态分布,成生各天卖出报的分数的概率值.(并规格化到0-1区间上)
根据供求关系选择计算亏损值adder.
SCount累加adder
T++
}
SAvg=SCount/STimDays;
If(SAvg <MinKuiVal)
MinKuiVal=SAvg
Z++
}
4代码[matlab]:
MinKuiVal=10000;
ZMax=15;
Z=0;
StimuDays=15;
T=0;
SCount=0;
SAvg=0;
a=0.2;
b=0.4;
ArrDay=[1:1:15];
KuiArr=[1:15];
while(Z<ZMax)
T=0;SCount=0;SAvg=0;
while(T<StimuDays)
p=normrnd(4.5,2,1,15);
%normrnd(miu,fi,m,n)产生均值为miu,方差为fi的m*n阶正态分布的随机数矩阵.
tempSum=sum(p);
p=p./tempSum;
disEZ=p.*ArrDay;
EZ=sum(disEZ);
if(Z>EZ)
SCount=SCount+(Z-EZ)*b;
else
SCount=SCount+(EZ-Z)*a;
end
T=T+1
end
SAvg=SCount/StimuDays;
if(SAvg<MinKuiVal)
MinKuiVal=SAvg;
end
KuiArr(Z+1)=SAvg;
Z=Z+1;
end
%outputAns
KuiArr
MinKuiVal