CF148D Bag of mice
题目描述
公主和龙🐉从一个初始装有 \(w\) 只白老鼠和 \(b\) 只黑老鼠的袋子中轮流抓老鼠,第一个从袋子里抓出白老鼠的人获胜。每一次龙从袋子里抓出一只老鼠时其他在袋子里的老鼠会变得惊慌,其中的一只会跳出袋子(公主抓老鼠时不会有老鼠跳出)。公主先手。公主获胜的概率是多少?另外,如果袋子里已经没有任何老鼠且没有一个人抓出了一只白老鼠,则龙获胜。自己跳出袋子的老鼠不是被抓出来的(不能决定胜者)。一只老鼠离开袋子后将永不返回袋子中。所有袋子中的老鼠被抓出去的概率是相等的,所有袋子中的老鼠受到惊吓跳出袋子的概率也是相等的。
思路
很适合刚学概率 DP 的人练练手!很有意思。
我们设 f[i][j] 表示在有 i 只白老鼠和 j 只黑老鼠时公主先手的获胜概率,g[i][j] 表示龙🐉先手的获胜概率。于是就有转移:
- 设 \(f[i][j]\) 为一次就抓到白老鼠和抓到黑老鼠但龙🐉输了的概率和,则 \(f[i][j] = i/(i+j) + j/(i+j) * (1-g[i][j-1])\)。
- 设 \(g[i][j]\) 为一次抓到白老鼠、抓到黑老鼠跑了白老鼠时公主输了、抓到黑老鼠跑了黑老鼠时公主输了的概率和,则\(g[i][j] = i/(i+j) + [j/(i+j)] * [i/(i+j-1)] * (1-f[i-1][j-1]) + [j/(i+j)] * [(j-1)/(i+j-1)] * (1-f[i][j-2])\)。
于是一个非常简短的代码就诞生了。
Code
#include<bits/stdc++.h>
using namespace std;
double f[1005][1005],g[1005][1005];
// f[i][j] 表示 i 只白老鼠和 j 只会给老鼠时公主的获胜概率,g[i][j] 同理。
int main(){
int w,b;
scanf("%d%d",&w,&b);
for(int i=1;i<=w;i++){
f[i][0]=g[i][0]=1; //记得处理边界条件。
for(int j=1;j<=b;j++){
f[i][j]=1.0*i/(i+j)+1.0*j/(i+j)*(1-g[i][j-1]);
g[i][j]=1.0*i/(i+j)+1.0*j/(i+j)*i/(i+j-1)*(1-f[i-1][j-1]);
if(j>=2) g[i][j]+=1.0*j/(i+j)*(j-1)/(i+j-1)*(1-f[i][j-2]); //判断下标是否会越界。
}
}
printf("%.9lf\n",f[w][b]);
return 0;
}
\(\sim\) ❀完结撒花❀ \(\sim\)

浙公网安备 33010602011771号