睡前小dp-hdu3853-概率dp

http://acm.hdu.edu.cn/showproblem.php?pid=3853

 

膜猴烧酒madoka

讲定义为dp[i][j] 位置为ij的魔法值期望,可以发现dp[i][j] = dp[i][j]*p1[i][j]+dp[i][j+1]*p2[i][j]+dp[i+1][j]*p3[i][j]+2

最后可以表示为

dp[x][y] = 1.0/(1-p[x][y][0])*(p[x][y][1]*dp[x][y+1]+p[x][y][2]*dp[x+1][y]+2.0);

递推的时候从右下角开始,向左上角递推。

有一个坑是p1=1 时,会出错,所以要特判一下。直接跳过。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

int R,C;
double dp[1010][1010],p[1010][1010][3];

int main()
{
    while(~scanf("%d%d",&R,&C))
    {
        for(int i=1;i<=R;i++)
        {
            for(int j=1;j<=C;j++)
            {
                scanf("%lf%lf%lf",&p[i][j][0],&p[i][j][1],&p[i][j][2]);
            }
        }

        memset(dp,0,sizeof dp);

        for(int x=R;x>=1;x--)
        {
            for(int y=C;y>=1;y--)
            {
                if(x==R&&y==C) continue;
                if(abs(p[x][y][0]-1.0)<(1e-7)) continue;
                dp[x][y] = 1.0/(1-p[x][y][0])*(p[x][y][1]*dp[x][y+1]+p[x][y][2]*dp[x+1][y]+2.0);
            }
        }

    /*
            for(int i=1;i<=R;i++)
        {
            for(int j=1;j<=C;j++)
            {
                printf("%lf ",dp[i][j]);
            }
            printf("\n");
        }
    */
        printf("%.3lf\n",dp[1][1]);
    }
}

 

posted @ 2015-12-06 23:29  Helica  阅读(216)  评论(0编辑  收藏  举报