概率dp总结
概率 DP 用于解决概率问题与期望问题,建议先对 概率 & 期望 的内容有一定了解。一般情况下,解决概率问题需要顺序循环,而解决期望问题使用逆序循环,如果定义的状态转移方程存在后效性问题,还需要用到 高斯消元 来优化。概率 DP 也会结合其他知识进行考察,例如 状态压缩,树上进行 DP 转移等。
我们这一次博客首先来讲dp去求概率的问题,这种问题一般都是顺序向后推的,主要还是dp的状态转移方程式一般还是比较难找到的
我们来通过几个例题来感受一下这种概率dp的题目
D. Bag of mice
思路:我们每一次抽都会产生4种情况,
1.公主抽到白鼠游戏直接结束,公主获胜
2.公主抽到黑鼠,巨龙抽到白鼠,巨龙获胜
3.公主抽到黑鼠,巨龙抽到黑鼠,跑了一只白鼠,需要考虑剩下老鼠的情况
4.公主抽到黑鼠,巨龙抽到黑鼠,跑了一只黑鼠,需要考虑剩下老鼠的情况
因为我们考虑的是公主获胜的概率,因此可以直接将第二种情况划掉
我们考虑当前怎么去写dp状态转移方程式
我们首先来想dp表达式表达的是什么,我们的dp[i][j]表示的是剩下i只白鼠,j只黑鼠,公主能够获胜的概率
我们来根据上面的三种情况,对dp进行转移,
dp[i][j]+=i/(i+j)//先手直接拿到白色
dp[i][j]+=j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2)*dp[i-1][j-2]//第三种情况
dp[i][j]+=j/(i+j)*(j-1)/(i+j-1)*(-2)/(i+j-2)*dp[i][j-3]//第四种情况
#include<bits/stdc++.h>
using namespace std;
#define double long double
int w,b;
double dp[1005][1005];
signed main()
{cin>>w>>b;for(int i=1;i<=w;i++){dp[i][0]=1.0;}for(int i=1;i<=b;i++){dp[0][i]=0.0;}for(int i=1;i<=w;i++){for(int j=1;j<=b;j++){dp[i][j]+=(double)i/(i+j);//先手取白色if(j>=2)dp[i][j]+=(double)j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2)*dp[i-1][j-2];if(j>=3)dp[i][j]+=(double)j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3];}}cout<<fixed<<setprecision(9)<<dp[w][b]<<'\n';return 0;
}