【hdu3853】Loops

题目描述

迷宫是一个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;
}