Desprition
袋子里有 (w) 只白鼠和 (b) 只黑鼠 ,A和B轮流从袋子里抓,谁先抓到白色谁就赢。A每次随机抓一只,B每次随机抓完一只之后会有另一只随机老鼠跑出来。如果两个人都没有抓到白色则B赢。A先抓,问A赢的概率。
(w,bleq 1000)
solution
概率 dp。
数据范围显然要求我们有个 (O(n^2)) 的做法。
设 (f[i][j]) 表示袋子里有 (i) 只白鼠 (j) 只黑鼠时 ,A赢得概率。
初始化:
- (f[i][1] = {iover {i+1}}) ,显然 (A) 只有在第一次抽到白鼠的时候才会赢,所以概率为 (iover{i+1})
- (f[i][0] = 1.0) ,当袋子里只有白鼠时,(A) 第一个取必胜。
转移:
-
(A) 第一次就取到了白鼠 (欧皇),就直接赢了,概率为 (iover{i+j})
-
(B) 第一次就取到了白鼠,因为 (B) 一取到 白鼠 (A) 就输了,所以不用考虑这种情况。
-
(A,B) 都取到了黑鼠,跑出来是黑鼠,首先两个人都抽到黑鼠的概率为 ({jover {i+j}} imes {j-1over {i+j-1}}) ,这时候在跑出一条黑鼠的概率为 ({j-2over{i+j-2}}) ,之后袋子里还剩下 (i) 只白鼠, (j-3) 只黑鼠,所以 (A) 赢得概率为 (f[i][j-3]) ,综上这种情况转移为 (f[i][j] += {jover {i+j}} imes {j-1over {i+j-1}} imes {j-2over{i+j-2}} imes f[i][j-3])
-
(A,B) 都取到黑鼠,跑出来一只白鼠,还是两个人都抽到黑鼠的概率为 ({jover {i+j}} imes {j-1over {i+j-1}}) , 这时再跑出来一只白鼠的概率就是 ({iover{i+j-2}}) ,之后袋子里还剩下 (i-1) 只白鼠,(j-2) 只黑鼠,那么 (A) 赢得概率就为 (f[i-1][j-2]) ,综上转移为 (f[i][j] += {jover {i+j}} imes {j-1over {i+j-1}} imes {iover{i+j-2}} imes f[i-1][j-2])
在转移到时候要注意一下边界问题,数组不能出现负下标,然后这道题就做完了 QAQ。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
double f[1010][1010];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
int main()
{
n = read(); m = read();
for(int i = 1; i <= n; i++)
{
f[i][0] = 1.0;
f[i][1] = 1.0 * i / (i+1);
}
for(int i = 1; i <= n; i++)
{
for(int j = 2; j <= m; j++)
{
f[i][j] = 1.0 * i / (i+j);
if(j >= 3) f[i][j] += 1.0 * j / (i+j) * (j-1) / (i+j-1) * (j-2) / (i+j-2) * f[i][j-3];
if(j >= 2) f[i][j] += 1.0 * j / (i+j) * (j-1) / (i+j-1) * i / (i+j-2) * f[i-1][j-2];
}
}
printf("%.9lf",f[n][m]);
return 0;
}