题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3853
题目概述:
在一个r*c的网格中有一个人有概率向右走,向下走或者留在原地,走一步产生2点花费,球走到终点的期望花费。
大致思路:
概率DP的入门题,学会了求概率要正着推,而求期望需要逆着推。
DP方程为:dp[i][j]=p1*dp[i][j]+p2*f[i][j+1]+p3*f[i+1][j];
复杂度分析:
根据DP方程,显然复杂度为O(r*c*T).
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <ctime> 7 #include <map> 8 #include <queue> 9 #include <cstring> 10 #include <algorithm> 11 using namespace std; 12 13 #define sacnf scanf 14 #define scnaf scanf 15 #define maxn 1010 16 #define maxm 26 17 #define inf 1061109567 18 #define Eps 0.00001 19 const double PI=acos(-1.0); 20 #define mod 7 21 #define MAXNUM 10000 22 void Swap(int &a,int &b) {int t=a;a=b;b=t;} 23 double Abs(double x) {return (x<0)?-x:x;} 24 typedef long long ll; 25 typedef unsigned int uint; 26 27 double p[3][maxn][maxn]; 28 double f[maxn][maxn]; 29 30 int main() 31 { 32 //freopen("data.in","r",stdin); 33 //freopen("data.out","w",stdout); 34 //clock_t st=clock(); 35 int r,c; 36 while(~scanf("%d%d",&r,&c)) 37 { 38 for(int i=1;i<=r;i++) 39 for(int j=1;j<=c;j++) 40 { 41 scanf("%lf%lf%lf",&p[0][i][j],&p[1][i][j],&p[2][i][j]); 42 f[i][j]=0; 43 } 44 for(int i=r;i>0;i--) 45 { 46 for(int j=c;j>0;j--) 47 { 48 if(fabs(1-p[0][i][j])<Eps) continue; 49 f[i][j]=(p[1][i][j]*f[i][j+1]+p[2][i][j]*f[i+1][j]+2)/(1-p[0][i][j]); 50 } 51 } 52 printf("%.3lf ",f[1][1]); 53 } 54 //clock_t ed=clock(); 55 //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); 56 return 0; 57 }