Broken robot

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;
}

posted @ 2019-05-27 18:10  a1b3c7d9  阅读(183)  评论(0编辑  收藏  举报