题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3853
类型:期望dp
大意:有一个迷宫,你的位置是[1][1],迷宫的出口是[r][c],即右下角。每个格子上写了三个数字,意味停在原地的概率、向右走的概率和向下走的概率。每走一格的消耗是2,问要从[1][1]走到[r][c]的期望消耗是多少。
题解:设dp[i][j]为从[1][1]到[i][j]的期望消耗,mp[i][j][0]~mp[i][j][2]为停、右、下三种概率。那么转移方程可以这样写:
右式中也有dp[i][j],所以把方程转化一下:dp[i][j] = dp[i][j]*mp[i][j][0] + dp[i][j+1]*mp[i][j][1] + dp[i+1][j]*mp[i][j][2];
注意到一个地方:dp[i][j] = (dp[i][j+1]*mp[i][j][1] + dp[i+1][j]*mp[i][j][2] + 2) / (1 - mp[i][j][0]);
(1 - mp[i][j][0]);要注意mp[i][j][0]为1的情况。假设为1,意味走到这里的话,一定就停下了。所以期望是0。
根据方程就能倒推了。
代码:
#include<iostream>
#include<cmath>
using namespace std;
#define MAXN 1010
#define eps 1e-8
double dp[MAXN][MAXN];
double mp[MAXN][MAXN][3];
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
for(int k = 0; k < 3; k++)
{
scanf("%lf", &mp[i][j][k]);
}
}
}
memset(dp, 0, sizeof(dp));
for(int i = n; i > 0; i--)
{
for(int j = m; j > 0; j--)
{
if(i == n && j == m)continue;
if(fabs(1 - mp[i][j][0]) < eps)continue;
dp[i][j] = (dp[i][j+1]*mp[i][j][1] + dp[i+1][j]*mp[i][j][2] + 2) / (1 - mp[i][j][0]);
};
}
printf("%.3lf\n", dp[1][1]);
}
}