您的位置:首页 > 其它

求期望问题小结 From ZJUTBBS

2017-03-03 15:29 218 查看
       前几天一直纠结在《地下迷宫》那题中,苦苦思索无果。在一个月黑风高的夜晚,终于开窍,原来期望就是这么回事。赛后DK跟我说求期望很简单,我以为是诓我去做这个题目。我心说,您老人家看什么不简单啊,何况你还是期望控。现在觉得果然是简单的,用我的人品做担保,真的很简单。

       先来看一个小例子:如图,从起点0,走到终点4。每次等概率地随机选择一条路走,(比如当前在0点,下一步分别有1/3的可能走到1,2,3点;对于1 点,下一步各有1/3的可能走到1点,0点,2点),求平均需要用几步走到终点4,也就是求走到4点所花步数的期望。



分析:
        要从0走到4,从第一步的角度来看,无非是三种途径:

①先走到1,然后经过若干过程从1走到4;

②先走到2,然后经过若干过程从2走到4;

③先走到3,然后经过若干过程从3走到4。
       假如我们已经知道了从1、2、3走到4所要花的平均步数分别是E(1)、E(2)、E(3),那么从0走到4的步数,有三种可能:E(1)+1、
E(2)+1、E(3)+1,而且这三种是等概率的。那么从0走到4的平均步数就是(E(1)+1+E(2)+1+E(3)+1)/3。现在我们并不知道 E(1)、E(2)、E(3)的值,得到的只是一个方程E(0)=(E(1)+E(2)+E(3))/3+1
       同样的,对于点2,我们可以列出方程E(2)=(E(0)+E(1)+E(3)+E(4))/4+1。
       有人说了,我靠,E(4)是什么东东?
       E(4)当然就是从4点走到4点所花的平均步数,显然有E(4)=0。
       联立方程组
        E(0)=(E(1)+E(2)+E(3))/3+1
        E(1)=(E(0)+E(1)+E(2))/3+1
        E(2)=(E(0)+E(1)+E(3)+E(4))/4+1
        E(3)=(E(0)+E(2)+E(4))/3+1
        E(4)=0
       图是我随手画的,求出来的解不整,保留两位小数如下:
       E[0]=8.38
       E[1]=9.14
       E[2]=6.90
       E[3]=6.10
       E[4]=0.00
       现在只要会编程解方程组就大功告成了。线性代数里讲过,可以用矩阵来表示线性方程组,用高斯消元法对矩阵进行处理,即可求解。有的小朋友没学线性代数,有 的和我一样学完后早忘到脚后跟去了。我是从网上搜了个高斯消元的代码来研究学习的。要不老衲买一赠一,顺道把高斯消元也解释一下吧。

-----------------------促销大派送之高斯消元---------------------------
    上述方程组整理可得(为了减少精度损失,在某些式子上乘个常数,使系数整一点):

3*E(0)  -E(1)  -E(2) -E(3)+0*E(4)=3

-E(0)+2*E(1)  -E(2)+0*E(3)+0*E(4)=3

-E(0)  -E(1)+4*E(2)  -E(3) -E(4)=4

-E(0)-0*E(1)  -E(2)-3*E(3)  -E(4)=3

0*E(0) +0*E(1) +0*E(2)+0*E(3)  +E(4)=0
    我们用一个5*5的二维数组a来描述等号左边各项的系数,用数组b来表示等号右边的常数项。直接用一个5*6的矩阵来表示当然也是可以的。数组的数据类型为double
           a              b

[0]  3 -1 -1 -1  0 | 3

[1] -1  2 -1  0 
0 |3

[2] -1 -1  4 -1 -1| 4

[3] -1  0 -1  3 -1 | 3

[4]  0 0  0 
0 1  | 0
    注意,在我的叙述中,行号列号都是从0开始编的。
    由方程组的性质,我们知道,可以给某一行乘上一个非零常数,可以把某一行乘一个非零常数加到另一行上去,可以任意调换两行的位置。这些操作都不影响方程组 的解,叫做行初等变换。我们利用行初等变换来处理矩阵。首先,我想让左边只留一个E(0),其他的E(0)系数都消掉。我们选择保留第0行,在第1、2、
3行上都加上第0行的1/3,矩阵变成了这样(只显示两位小数,下同):
   3.00 -1.00 
-1.00  -1.00  0.00|  
3.00
   0.00  1.67 
-1.33  -0.33  0.00|  
4.00
   0.00 -1.33  
3.67  -1.33 -1.00|  
5.00
   0.00 -0.33 
-1.33   2.67 -1.00|  
4.00
   0.00  0.00  
0.00   0.00  1.00|  
0.00
    第0行就固定不动了,接着我让下面四行只留一个E(1),其他的消掉。方法是在第2行上加上第1行的4/5,在第3行上加上第1行的1/5。处理后:
   3.00 -1.00 
-1.00  -1.00  0.00|  
3.00
   0.00  1.67 
-1.33  -0.33  0.00|  
4.00
   0.00  0.00  
2.60  -1.60 -1.00|  
8.20
   0.00  0.00 
-1.60   2.60 -1.00|  
4.80
   0.00  0.00  
0.00   0.00  1.00|  
0.00
    从上面的步骤可以看出,在消元的时候,我们需要从下面剩下的行中选择一个需要保留的行,这里称作主元行。选择的标准是什么?比如上一步,我们完全可以把第 1行加上第3行的5倍,把第2行加上第3行的-4倍。我看的那篇文章上说,选择该列中绝对值最大的那一行作为主元行,这样可以减少精度损失。好吧,我们相
信这个说法。假设a[1][1]这个位置不是1.67,而是0.67,那么这一列中绝对值最大的系数就是a[2][1]的-1.33(注意,第0行是不参
与比较的,它已经固定下来了)。那我们就交换第1、2行,把-1.33这一行提到上面,然后再执行消元操作,把这一列的下面都消成0。
    如果处理到某一列的时候,发现这一列剩下的系数竟然全是0了,比如这样的:
    1 2 3 4| 5
    0 6 7 8| 9
    0 0 0 1| 2
    0 0 0 2| 4
    第2列剩下的全是0了,找不到主元行了,这说明该矩阵的秩小于元数,方程组解不出唯一解来。通俗点说,就是这些方程里有水货,表面上看是4个方程,可仔细一瞧,第2行和第3行本质上是一样的,当然解不出。
    好了,回到我们刚才的例子,通过一番处理之后,矩阵的左下角全变成0了。这称为行阶梯式。
   3.00 -1.00 
-1.00  -1.00  0.00|  
3.00
   0.00  1.67 
-1.33  -0.33  0.00|  
4.00
   0.00  0.00  
2.60  -1.60 -1.00|  
8.20
   0.00  0.00  
0.00   1.62 -1.62|  
9.85
   0.00  0.00  
0.00   0.00  1.00|  
0.00
    根据最后一行,可以确定E(4)的值,我们把它存到x[4]里。把E(4)代入到3式,可以解出E(3);把E(3)、E(4)代入2式,解出E(2)……
    代码实现如下:

#define EPS 1e-10
int N;
#define MAX 100
double a[MAX][MAX],b[MAX],x[MAX];
bool flag;

double ab(double x)
{
return (x>=0)?x:-x;
}
void Gauss()
{
flag=1;
double maxi,d;
int index,i,j,k;
for(k=0;k<N;k++)
{
maxi=0;
for(i=k;i<N;i++)//找该列绝对值最大的行
{
if(ab(a[i ][k])>maxi)
{
index=i;
maxi=ab(a[i ][k]);
}
}
if(maxi<EPS)//如果剩下的全是0,失败返回
{
flag=0;
return;
}
if(index!=k)//把主元行交换到上面来
{
swap(b[index],b[k]);
for(j=k;j<N;j++)
swap(a[index][j],a[k][j]);
}
for(i=k+1;i<N;i++)//把非主元行的系数消掉
{
d=a[i ][k]/a[k][k];
b[i ]-=b[k]*d;
a[i ][k]=0;
for(j=k+1;j<N;j++)
a[i ][j]-=a[k][j]*d;
}
}
//至此,已经得到一个行阶梯式
for(i=N-1;i>=0;i--)//从底向上依次代入求解
{
for(j=i+1;j<N;j++)
b[i ]-=a[i ][j]*x[j];
x[i ]=b[i ]/a[i ][i ];
}
}

------------------------赠品End------------------------
    高斯消元解方程组的复杂度是O(N^3),回到地下迷宫这题,对所有的连通点联立方程组。连通点的个数不超过100,代码见这里
http://bbs.zjut.com/viewthread.php?tid=1167909&page=1#pid6158985(链接已经失效)

扩展1:POJ 3682 King Arthur's Birthday Celebration
    http://acm.pku.edu.cn/JudgeOnline/problem?id=3682
    题目大意是说扔硬币,有p的概率是正面,1-p的概率是反面。每天扔一次,直到累计扔出k个正面为止。在扔硬币期间,第一天花1千块钱,第二天花3千,第三天花5千……
    求平均扔几次会停止,平均会花多少钱。
   
以k=3,p=0.5为例,按已扔出几个正面来区分,共有4种状态。各状态之间按如下的概率转移。




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: