CF24D Broken robot

CF

洛咕

题意:n行m列格子.机器人最初是在第i行第j列的格子上.目的是去第n行任意一个格子.机器人每一步可以停留在当前格子,向左移动,向右移动,或者移动到当前下方的格子上.如果机器人在最左边的列不能向左移动,如果它是在最右边的列不能向右移动.在每一步中,所有可能的动作的概率相同.求机器人到达第n行所需行动次数的期望值.\((1<=n,m<=1000)\)

分析:设\(f[i][j]\)表示机器人从位置\((i,j)\)走到最后一行所需行动次数的期望值.

\(f[i][1]=\frac{1}{3}(f[i][1]+f[i][2]+f[i+1][1])+1\)如果当前在第1列,则只有不动,向右和向下三种情况可以走;

\(f[i][m]=\frac{1}{3}(f[i][m]+f[i][m-1]+f[i+1][m])+1\)如果当前在第m列,则只有不动,向左和向下三种情况可以走;

否则,\(f[i][j]=\frac{1}{4}(f[i][j]+f[i][j-1]+f[i][j+1]+f[i+1][j])+1\)

但是,根据转移方程我们发现第i行的状态受第i+1行的状态的影响,也就是具有后效性,不能直接DP.故考虑从i+1推出i;

\(f[i+1][j]\)看作已知数,则上述转移方程可以写成一元一次方程,共M个方程,考虑高斯消元.注意到不论题目如何,矩阵的系数都是有规律的,设M=5,则系数矩阵为

\[\left\{ \begin{matrix} -\frac{2}{3} & \frac{1}{3} & 0 & 0 & 0\\ \frac{1}{4} & -\frac{3}{4} & \frac{1}{4} & 0 & 0 \\ 0 & \frac{1}{4} & -\frac{3}{4} & \frac{1}{4} & 0 \\ 0 & 0 & \frac{1}{4} & -\frac{3}{4} & \frac{1}{4}\\ 0 & 0 & 0 & \frac{1}{3} & -\frac{2}{3} \end{matrix} \right\} \]

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
const int N=1005;
double a[N][N],f[N][N];
int main(){
    int n=read(),m=read(),x=read(),y=read();
    if(x==n){puts("0.0000000000");return 0;}
    if(m==1){printf("%.10lf",(n-x)*2.0);return 0;}
//两个特判.
    for(int i=n-1;i>=x;--i){
		a[1][1]=a[m][m]=-2.0/3.0;
		a[1][2]=a[m][m-1]=1.0/3.0;
		a[1][m+1]=-f[i+1][1]/3.0+1;
		a[m][m+1]=-f[i+1][m]/3.0+1;
		for(int j=2;j<m;++j){
	    	a[j][j]=-3.0/4.0;
	    	a[j][j-1]=a[j][j+1]=1.0/4.0;
	    	a[j][m+1]=-f[i+1][j]/4.0+1;
		}//以上都是高斯消元对矩阵赋初值
		for(int j=1;j<m;++j){
	    	double cnt=1.0*a[j+1][j]/a[j][j];
	    	a[j+1][j+1]-=a[j][j+1]*cnt;
	    	a[j+1][m+1]-=a[j][m+1]*cnt;
		}//从上往下高斯消元
		for(int j=m;j>1;--j){
	    	double cnt=1.0*a[j-1][j]/a[j][j];
	    	a[j-1][m+1]-=a[j][m+1]*cnt;
		}//从下往上回代
		for(int j=1;j<=m;++j)
	    	f[i][j]=a[j][m+1]/a[j][j];//保存结果
    }
    printf("%.10lf\n",abs(f[x][y]));//不知道为什么我答案每次输出的正好是负数
    return 0;
}

posted on 2019-06-18 20:14  PPXppx  阅读(103)  评论(0编辑  收藏  举报