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