Broken robot
在\(n\times m\)的网格上,有一个机器人在\((x,y)\)上,它可以等概率选择向下向右向左移动,或者停留原地,询问机器人到第n行的所走的步数的数学期望, \(1<=n,m<=1000\)。
解
易知数学期望题目,而样本空间无限大,考虑有后效性递推,设\(f[x][y]\)表示机器人从(x,y)到最后一行的所走步数的数学期望,不难有
\[if(y==1),f[x][y]=\frac{1}{3}(f[x+1][y]+f[x][y+1]+f[x][y])+1
\]
\[if(y==m\&\&m>1),f[x][y]=\frac{1}{3}(f[x+1][y]+f[x][y-1]+f[x][y])+1
\]
(注,对于m=1,我们还需要特判)
\[else,f[x][y]=\frac{1}{4}(f[x+1][y]+f[x][y-1]+f[x][y+1]+f[x][y])+1
\]
于是我们可以凭借此,得到若干个方程,以此高斯消元,但是注意其实一个方程中的未知数是很少,而且十分有规律,对行列进行考虑,于是实际上对于每一行进行高斯消元,实际进行的时间复杂度并不高,所以总时间复杂度\(O(nm)\),另外对于手动消元,要注意先保留最高位,再eam。
参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
double jz[1005][1005],
dp[1005][1005];
int main(){
int n,m,x,y;
scanf("%d%d%d%d",&n,&m,&x,&y);
if(m==1){
printf("%.10lf",(n-x)*2.0);
return 0;
}
for(int i(n-1),j,k;i;--i){
jz[1][0]=-1-dp[i+1][1]/3,jz[1][1]=-2.0/3,jz[1][2]=1.0/3;
jz[m][0]=-1-dp[i+1][m]/3,jz[m][m]=-2.0/3,jz[m][m-1]=1.0/3;
for(j=2;j<m;++j)
jz[j][0]=-1-dp[i+1][j]/4,jz[j][j]=-3.0/4,jz[j][j-1]=jz[j][j+1]=1.0/4;
for(j=1;j<=m;++j){
jz[j][j+1]/=jz[j][j],jz[j][0]/=jz[j][j],jz[j][j]=1;
jz[j+1][j+1]-=jz[j][j+1]*jz[j+1][j],jz[j+1][0]-=jz[j][0]*jz[j+1][j],jz[j+1][j]=0;
}for(j=m;j;--j)jz[j-1][0]-=jz[j][0]*jz[j-1][j],jz[j-1][j]=0;
for(j=1;j<=m;++j)dp[i][j]=jz[j][0];
}printf("%.10lf",dp[x][y]);
return 0;
}