【dp选讲】浅谈概率dp
作者:互联网
【dp选讲】概率与期望
说在前面
如果您此前还没有了解过任何有关概率的内容的话,请先自行学习概率和期望的相关定理,然后再食用本博客。
概率选题
注:概率和期望一般都是计算题,所以本博客仅从解题的角度向您展示概率和期望,具体做题的时候还是有一点思考难度的,但是一般比较统一。
CF148D
题目大意:有两个人往袋子里面抓老鼠,老鼠分为两类,一类是白老鼠,一类是黑老鼠,获胜规则是谁先抓到白老鼠谁就获胜。A抓老鼠的时候会附带着有一只老鼠溜出袋子,而B不会。如果最后是A抓到白老鼠或老鼠都跑光了,A也获胜,请问B获胜的概率是多少。输入:N只白老鼠和M只黑老鼠。
分析:
设 $$dp[i][j]$$ 为袋子里面有 i 只白老鼠和 j 只黑老鼠时的轮到B的获胜概率。
初始化:$$dp[0][j]=0$$ ,$$dp[i][0]=1$$,意思分别是:如果一只白老鼠都没有的话,就必输无疑;如果没有黑老鼠,反而全是白老鼠的话,那就必胜无疑。
先考虑B在当前状态下一次就抓到白老鼠的欧皇行为:
\[概率为:\frac{i}{i+j} \]接着思考B拿到黑老鼠,而A拿到白老鼠的非酋行为:
\[概率为:\frac{j}{i+j}*\frac{i}{i+j-1} \]【注:这是个分布事件,第一步是B非酋拿黑摆烂,第二步才是A欧皇拿白。】
第三种:B抓到黑老鼠,A也抓到黑老鼠,最后又跑出一只黑老鼠,此时的概率是:
\[\frac{j}{i+j}*\frac{j-1}{i+j-1}*\frac{j-2}{i+j-2} \]上面这种情况可以转移到\(dp[i][j-3]\).
第四种:依旧是两人抓到黑老鼠,但是跑出来的是白老鼠,此时的概率为:
\[\frac{j}{i+j}*\frac{j-1}{i+j-1}*\frac{i}{i+j-2} \]可转移到\(dp[i-1][j-2]\).
根据以上式子,dp转移即可。
#include<iostream>
#include<cstdio>
#define Maxn 5000
using namespace std;
typedef double db;
int n,m;
db dp[Maxn][Maxn];
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) dp[i][0]=1;
for(int j=1;j<=m;j++) dp[0][j]=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
dp[i][j]+=(db)i/(i+j);
if(j>=3)
dp[i][j]+=(db)j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3];
if(j>=2)
dp[i][j]+=(db)j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2)*dp[i-1][j-2];
}
}
printf("%.9lf",dp[n][m]);
return 0;
}
[Scout YYF I][http://poj.org/problem?id=3744]
题目大意:在一个数轴上,有n个雷。一开始,你在原点,现在,你有p的概率走一步,有(1-p)的概率走两步,请问你有多大的概率可以安全通过雷阵?
分析:
直接算概率是不好求的,我们不如利用容斥原理,求出我们必定踩雷的概率(真非酋才能完成的壮举),最后用1减去即可。
于是乎,我们可以逐步求解,求出我们踩第一个雷的概率,接着是第二个雷的概率,以此类推。
很自然地,我们列出转移方程式:
\[dp[i]=p*dp[i-1]+(1-p)*dp[i-2] \]但是!这是一道多测题,单测都是极限的\(10^9\)了,线性递推肯定不可行,我们考虑优化。
仔细思考——嗯,这道题是不是有点似曾相识?看起来有点像斐波那契的递推式不是吗?那么这道题也许可以用矩阵乘法来优化。
于是,我们能列出这么一个矩阵的递推式:
\[p 1-p\\ 1 0 \]幂次方取得是每一段的长度。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Maxn 20000000
using namespace std;
typedef double db;
db p;
int n,pos[Maxn];
struct Matrix{
double mat[2][2];
void clear() {memset(mat,0,sizeof(mat));}
void idenaty() {clear();for(int i=0;i<2;i++)mat[i][i]=1;}
};
Matrix mul(Matrix a,Matrix b) {
Matrix res;
res.clear();
for(int i=0;i<2;i++) {
for(int j=0;j<2;j++) {
res.mat[i][j]=0;
for(int k=0;k<2;k++) {
res.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
}
}
}
return res;
}
Matrix power(Matrix x,int p) {
Matrix res;
res.idenaty();
Matrix base=x;
while(p) {
if(p&1) res=mul(res,base);
base=mul(base,base);
p>>=1;
}
return res;
}
int main() {
while(scanf("%d%lf",&n,&p)!=EOF) {
for(int i=1;i<=n;i++)
scanf("%d",&pos[i]);
db ans=1;
sort(pos+1,pos+n+1);
Matrix a;
a.clear();
a.mat[0][0]=p;a.mat[0][1]=1-p;
a.mat[1][0]=1;a.mat[1][1]=0;
Matrix ret;
ret.clear();
ret=power(a,pos[1]-1);
ans*=(1-ret.mat[0][0]);
for(int i=2;i<=n;i++) {
if(pos[i]==pos[i-1]) {continue;}
ret.clear();
ret=power(a,pos[i]-pos[i-1]-1);
ans*=(1-ret.mat[0][0]);
}
printf("%.7lf\n",ans);
}
return 0;
}
标签:老鼠,概率,frac,浅谈,int,选讲,include,dp 来源: https://www.cnblogs.com/lxxwxxxxx/p/15550670.html