题目描述
迷宫是一个R*C的布局,每个格子中给出停留在原地,往右走一个,往下走一格的概率,起点在(1,1),终点在(R,C),每走一格消耗两点能量,求出最后所需要的能量期望
输入
输入有多组数据。对于每组数据:
第一行两个整数r、c,表示迷宫的大小(2 <= r, c <= 1000);
接下来一个 (3r)* c 的矩阵,每三个数表示该点停留在原地,往右走一个,往下走一格的概率。
输出
需要的能量期望,保留三位小数。
样例输入
2 2
0.00 0.50 0.50 0.50 0.00 0.50
0.50 0.50 0.00 1.00 0.00 0.00
样例输出
6.000
题解
期望dp。设dp[ i ][ j ]表示从点(i,j)到终点所需的能量期望,则dp[ r ][ c ] = 0。
对于点(i,j),设停留在原地的概率为p0,向下走为p1,向右走为p2,那么我们可以得到公式: dp[ i ][ j ]=p0 * dp[ i ][ j ] + p1 * dp[ i+1 ][ j ] + p2 * dp[ i ][ j+1 ] +2 。
换句话说,如果停留原地的概率为1,那么continue,否则 dp[ i ][ j ]=( p[ i ][ j ][ 1 ] * dp[ i ][ j+1 ] + p[ i ][ j ][ 2 ] * dp[ i+1 ][ j ] + 2 ) / ( 1 - p[ i ][ j ][ 0 ] )。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=1010; const double eps=1e-5; double dp[maxn][maxn],p[maxn][maxn][3]; int r,c; int main(){ while(scanf("%d%d",&r,&c)!=EOF){ memset(p,0,sizeof(p)); memset(dp,0,sizeof(dp)); for(int i=1;i<=r;i++) for(int j=1;j<=r;j++) scanf("%lf%lf%lf",&p[i][j][0],&p[i][j][1],&p[i][j][2]); dp[r][c]=0; for(int i=r;i>=1;i--) for(int j=c;j>=1;j--){ if(i==r&&j==c) continue; if(fabs(1.0-p[i][j][0])<eps) continue; dp[i][j]=(p[i][j][1]*dp[i][j+1]+p[i][j][2]*dp[i+1][j]+2.0)/(1-p[i][j][0]); } printf("%.3lf ",dp[1][1]); } return 0; }