睡前小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]); } }