题意:r*c 的方格地图,起点在 (1,1),终点在(r , c),方向只有三种:呆在原地,向右走,向下走,每走一步花费为 2 。
给出每个点三种方向走的概率,求出从起点到终点走的期望花费。
既然求期望,那么就倒着走。
设dp[i][j]是当在(i , j)点时,到达终点的期望步数,因为期望的线性关系,期望可以由若干个子期望求出,那么对于(i,j) 点的三种方向,下一步可能走到点为: (i,j),(i,j+1),(i+1,j);
假设概率分别为p[1],p[2],p[3];
那么由期望公式可得:
dp[i][j]=p[1]*dp[i][j]+p[2]*dp[i][j+1]+p[3]*dp[i+1][j]+2;
化简可得:
dp[i][j]=(p[2]*dp[i][j+1]+p[3]*dp[i+1][j]+2)/(1-p[1]);
转移就完成了。
再来考虑边界: dp[r][c]=0;
求期望感觉难在对状态的转移,要将这个点所有的下一步的状态都考虑好,然后乘以其概率,再累加子期望*子概率。那么得出来的就是父期望,公式也就是:E(aX+bY)=a*E(X)+b*E(Y).
ps:数学不好是硬伤。
#include<algorithm>
#include<string>
#include<string.h>
#include<queue>
#include<vector>
#include<stack>
#include<math.h>
#include<map>
#include<stdio.h>
#include<iostream>
using namespace std;
int r,c;
double dp[1005][1005],p[1005][1005][4];
int main()
{
while(scanf("%d%d",&r,&c)!=EOF)
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
for(int k=1;k<=3;k++)
scanf("%lf",&p[i][j][k]);
}
}
dp[r][c]=0;
for(int i=r;i>=1;i--)
{
for(int j=c;j>=1;j--)
{
if(i==r&&j==c||p[i][j][1]==1)
continue;
dp[i][j]=(p[i][j][2]*dp[i][j+1]+p[i][j][3]*dp[i+1][j]+2)/(1.0-p[i][j][1]);
}
}
printf("%.3f\n",dp[1][1]);
}
return 0;
}