HDU--3853(概率DP)
2015-01-02 17:25:15
思路:比较入门的一道概率DP,其实一开始学就不太理解为什么算期望一定要逆推,做完这题稍有领悟。
首先要建立递推方程,找概率“1”,发现从自己出发的所有方式概率和就为1,那么就以自己建立方程:
dp[i][j] = (dp[i][j + 1] + 2) * P(right) + (dp[i + 1][j] + 2) * P(down) + (dp[i][j] + 2) * P(stay)
要注意dp数组清零,防止不同组数据残留问题。然后还要防止计算根本不能达到终点的点。(这里dp初始化为-1)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 1010; 22 23 int R,C; 24 double g[maxn][maxn][3]; 25 double dp[maxn][maxn]; 26 27 int main(){ 28 while(scanf("%d%d",&R,&C) != EOF){ 29 for(int i = 1; i <= R; ++i){ 30 for(int j = 1; j <= C; ++j){ 31 scanf("%lf%lf%lf",&g[i][j][0],&g[i][j][1],&g[i][j][2]); 32 } 33 } 34 //memset(dp,0,sizeof(dp)); 35 for(int i = 1; i <= R; ++i) 36 for(int j = 1; j <= C; ++j) 37 dp[i][j] = -1.0; 38 dp[R][C] = 0.0; 39 for(int i = R; i >= 1; --i){ 40 for(int j = C; j >= 1; --j){ 41 if(i == R && j == C) continue; 42 double top = 2.0 * g[i][j][0]; 43 double bot = (1.0 - g[i][j][0]); 44 if(j < C && dp[i][j + 1] != -1.0){ 45 top += g[i][j][1] * (dp[i][j + 1] + 2.0); 46 } 47 if(i < R && dp[i + 1][j] != -1.0){ 48 top += g[i][j][2] * (dp[i + 1][j] + 2.0); 49 } 50 if(bot) dp[i][j] = top / bot; 51 //printf("dp[%d][%d] : %.3f\n",i,j,dp[i][j]); 52 } 53 } 54 printf("%.3f\n",dp[1][1]); 55 } 56 return 0; 57 }