• [概率DP][消元法][CF24D]损坏的机器人


    Description

    有一只坏了的机器人站在一个(n imes m)的网格里,初始位置在((x,y))。现在每个单位时间内它会随机选左右下三个方向走,如果它随机的方向会走出网格就不会往这个方向走。当然这个机器人也可能原地停留一个单位时间。求机器人走到第(n)行的期望时间。

    满足(n,mle 10^3,1le xle n,1le yle m)

    Solution

    考虑期望DP。

    经过变换可使得(x=1)

    正着不好做,不妨倒过来,计算从最后一行任意位置到达((1,y))的期望时间。设(f_{x,y})是到达((x,y))的期望时间。

    不妨假设我们已经计算完了到达第(i-1)行每一个位置的期望时间(f_{i-1,1},f_{i-1,2},cdots,f_{i-1,m})。现在记(x_1,x_2,cdots,x_m)(f_{i,1},f_{i,2},cdots,f_{i,m})(t_1,t_2,cdots,t_m)(f_{i-1,1},f_{i-1,2},cdots,f_{i-1,m})

    容易列出状态转移方程:

    [egin{cases}&x_1=frac{1}{3}(x_1+x_2+t_1)+1\&x_i=frac{1}{4}(x_{i-1}+x_i+x_{i+1}+t_i)+1;;;;;;(1<i<m)\&x_m=frac{1}{3}(x_{m-1}+x_m+t_m)+1end{cases} ]

    整理得:

    [egin{cases}&2x_1-x_2=t_1+3\&3x_i-x_{i-1}-x_{i+1}=t_i+4;;;;;;(1<i<m)\&2x_m-x_{m-1}=t_m+3end{cases} ]

    可以发现这个方程并没有办法直接DP。

    所以不妨考虑解方程。将上述方程写成增广矩阵形式如下:

    [left[egin{array}{c|c}egin{matrix}2 & -1\-1 & 3 & -1\& -1 & 3 & -1\&& cdots & cdots & cdots\&&& -1 & 3 & -1\&&&& -1 & 3 & -1\&&&&& -1 & 2end{matrix}&egin{matrix}t_1+3\t_2+4\t_3+4\cdots\t_{m-2}+4\t_{m-1}+4\t_m+3end{matrix}end{array} ight] ]

    逐行消元。假设我们已经消掉了第(i-1)行,要消第(i)行,矩阵局部如下:

    [left[egin{array}{c|c}egin{matrix}1 & -A\-1 & 3 & -1end{matrix}&egin{matrix}y_{i-1}\y_iend{matrix}end{array} ight] ]

    两式相加得:

    [left[egin{array}{c|c}egin{matrix}1 & -A\& 3-A & -1end{matrix}&egin{matrix}y_{i-1}\y_{i-1}+y_iend{matrix}end{array} ight] ]

    将主对角线上的数消成(0)

    [left[egin{array}{c|c}egin{matrix}1 & -A\& 1 & -frac{1}{3-A}end{matrix}&egin{matrix}y_{i-1}\frac{y_{i-1}+y_i}{3-A}end{matrix}end{array} ight] ]

    我们就能得到迭代式(A'=frac{1}{3-A})。消元完成后反解回去即可。

    处理完边界条件后,容易写出代码。

    Code

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,x,y;
    double A[1001],B[1001],F[1001][1001];
    int main(){
    	scanf("%d%d%d%d",&n,&m,&x,&y);
    	n-=x-1;
    	if(m==1||m==2){printf("%d
    ",(n-1)*(m+1));return 0;}
    	A[1]=0.5;
    	for(int i=2;i<m;i++)A[i]=1/(3-A[i-1]);
    	for(int i=n-1;i>=1;i--){
    		B[1]=(F[i+1][1]+3)/2;
    		for(int j=2;j<m;j++)B[j]=(B[j-1]+F[i+1][j]+4)*A[j];
    		F[i][m]=(B[m-1]+F[i+1][m]+3)/(2-A[m-1]);
    		for(int j=m-1;j>=1;j--)F[i][j]=B[j]+F[i][j+1]*A[j];
    	}
    	printf("%.10lf
    ",F[1][y]);
    }
    
  • 相关阅读:
    final,static,this,super 关键字总结
    Java基础知识(三)
    Java基础知识(二)
    Java基础知识(一)
    MyBatis重要核心概念
    Mybatis执行SQL的完整过程及四大组件介绍
    Mybatis之plugin插件设计原理
    Spring MVC 9大组件概述
    Log4j的使用
    Git的介绍及使用
  • 原文地址:https://www.cnblogs.com/eztjy/p/11597531.html
Copyright © 2020-2023  润新知