pro:给定N*M的矩阵,以及初始玩家位置。 规定玩家每次会等概率的向左走,向右走,向下走,原地不动,问走到最后一行的期望。保留4位小数。

sol:可以列出方程,高斯消元即可,发现是三角矩阵,O(N*M)----元素个数。  也可以用反复逼近答案。 反复做,dp[i][j]=(dp[i][j+1]+dp[i][j-1]+dp[i][j]+dp[i-1][j])/d[j]+1.0  为了使逼近效果更好,我每次先左一次,再右一次。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1010;
double dp[maxn][maxn]; int d[maxn];
int main()
{
    int N,M,x,y;
    scanf("%d%d%d%d",&N,&M,&x,&y);
    rep(i,1,M){
        d[i]=2;
        if(i>1) d[i]++;
        if(i<M) d[i]++;
    }
    rep(i,x+1,N){
        rep(t,1,20){
            rep(j,1,M) dp[i][j]=(dp[i][j+1]+dp[i][j-1]+dp[i][j]+dp[i-1][j])/d[j]+1.0;
            for(int j=M;j>=1;j--) dp[i][j]=(dp[i][j+1]+dp[i][j-1]+dp[i][j]+dp[i-1][j])/d[j]+1.0;
        }
    }
    printf("%.10lf\n",dp[N][y]);
    return 0;
}

 

 

 

高斯消元版本:

由于同行之间有后效性,所以我们在相邻层之间列方程,然后高斯消元。  即N次高斯消元,由于是上三角矩阵,所以每次高斯消元的复杂度是线性的:每行消去一个,然后倒着求解即可。  

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1010;
double a[maxn][maxn],res[maxn],ans[maxn][maxn];
int N,M,X,Y;
void Guass()
{
    for(int R=N-1;R>=X;R--){
        rep(i,1,M) res[i]=ans[R+1][i];
        a[1][1]=a[M][M]=-2.0/3.0; a[1][2]=a[M][M-1]=1.0/3.0;
        res[1]=-ans[R+1][1]/3.0-1; res[M]=-ans[R+1][M]/3.0-1;
        rep(i,2,M-1){
           a[i][i-1]=a[i][i+1]=1.0/4.0;
           a[i][i]=-3.0/4.0;
           res[i]=-ans[R+1][i]/4.0-1;
        }
        rep(i,1,M-1){
            double t=a[i+1][i]/a[i][i];
            a[i+1][i]-=t*a[i][i];
            a[i+1][i+1]-=t*a[i][i+1];
            //a[i+1][i+2]-=t*a[i][i+2]; 不知道为什么这行删去了也能AC
            res[i+1]-=t*res[i];
        }
        ans[R][M]=res[M]/a[M][M];
        for(int i=M-1;i>=1;i--){
            ans[R][i]=(res[i]-a[i][i+1]*ans[R][i+1])/a[i][i];
        }
    }
}
int main()
{
    scanf("%d%d%d%d",&N,&M,&X,&Y);
    if(M==1){
        printf("%.10lf\n",2.0*(N-X));
        return 0;
    }
    Guass();
    printf("%.10lf\n",ans[X][Y]);
    return 0;
}