引用:https://blog.csdn.net/auto_ac/article/details/9907881
很多概率题总逃不开用dp转移。
期望题总是倒着推过来的,概率是正着推的,多做题就会理解其中的原因
有些期望题要用到有关 概率 或 期望的常见公式或思想
遇到dp转移方程(组)中有环的,多半逃不出高斯消元(手动 和 写代码 两种)
这套题中还有道树上的dp转移,还用dfs对方程迭代解方程, 真是大开眼界了
当然还有与各种算法结合的题,关键还是要学会分析
当公式或计算时有除法时, 特别要注意分母是否为零
入门题:http://acm.hdu.edu.cn/showproblem.php?pid=3853
题意:一开始在矩阵左上角,每次有三种可能的选择(有对应的概率)向下走、向右走、原地不动,每次都有2的消耗,问到矩阵右下角的期望消耗是多少?
分析:设dp[i][j]表示从位置[i,j]到右下角的期望,那么dp[i][j]=dp[i][j]*(原地不动的概率)+dp[i+1][j]*(向下走的概率)+dp[i][j+1]*(向右走的概率)移项得公式

#include<cstdio>
using namespace std;
const int M=1003;
double p[M][M][5],dp[M][M];
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++)
scanf("%lf%lf%lf",&p[i][j][1],&p[i][j][2],&p[i][j][3]);
dp[n][m]=0;
for(int i=1;i<=n;i++)
dp[i][m+1]=0;
for(int i=1;i<=m;i++)
dp[n+1][i]=0;
for(int i=n;i>0;i--){
for(int j=m;j>0;j--){
if(p[i][j][1]==1||i==n&&j==m)
continue;
dp[i][j]=(dp[i+1][j]*p[i][j][3]+dp[i][j+1]*p[i][j][2]+2)/(1-p[i][j][1]);
}
}
printf("%.3f\n",dp[1][1]);
}
return 0;
}
