题目:
https://www.luogu.com.cn/problem/CF148D
袋子里有 n n n只白鼠和 m m m只黑鼠 , A A A和 B B B轮流从袋子里抓,谁先抓到白色谁就赢。 A A A每次随机抓一只, B B B每次随机抓完一只之后会有另一只随机老鼠跑出来。如果两个人都没有抓到白色则 B B B赢。 A A A先抓,问 A A A赢的概率。
思路:
三元组 ( A , i , j ) (A,i,j) (A,i,j)表示有 i i i只白鼠, j j j只黑鼠, A A A先抓这种状态
用 f ( A , i , j ) f(A,i,j) f(A,i,j)表示以 ( A , i , j ) (A,i,j) (A,i,j)表示的状态开始游戏, A A A赢的概率,答案为 f ( A , n , m ) f(A,n,m) f(A,n,m)。
( A , i , j ) i i + j → A 赢 ( A , i , j ) j i + j → ( B , i , j − 1 ) \begin{aligned} &(A,i,j)\quad\frac{i}{i+j}\rightarrow\quad A赢\\ &(A,i,j)\quad\frac{j}{i+j}\rightarrow\quad (B,i,j-1)\\ \end{aligned} (A,i,j)i+ji→A赢(A,i,j)i+jj→(B,i,j−1)
表示 ( A , i , j ) (A,i,j) (A,i,j)有 i i + j \frac{i}{i+j} i+ji 的概率直接进入赢得状态, j i + j \frac{j}{i+j} i+jj的概率进入 ( B , i , j − 1 ) (B,i,j-1) (B,i,j−1)这种状态。所以有
f ( A , i , j ) = i i + j ∗ 1 + j i + j ∗ f ( B , i , j − 1 ) f(A,i,j)=\frac{i}{i+j}*1+\frac{j}{i+j}*f(B,i,j-1) f(A,i,j)=i+ji∗1+i+jj∗f(B,i,j−1)
同理分析 ( B , i , j ) (B,i,j) (B,i,j)。
可以直接记忆化搜索,注意初始值的分析。
#include<bits/stdc++.h>
using namespace std;
const int N=1009;
int n,m;
double dp[2][N][N];
double dfs(int x,int y,int z)
{
if(!y)
return 0;
if(!z&&x)
return 1;
if(!z)
return 0;
if(z<0&&x)
return 0;
if(dp[x][y][z]!=0)
return dp[x][y][z];
if(x)
dp[x][y][z]+=(double)z/(y+z)*dfs(0,y,z-1)+(double)y/(y+z);
else
dp[x][y][z]+=(double)z/(y+z)*(((double)z-1)/(y+z-1)*dfs(1,y,z-2)+(double)y/(y+z-1)*dfs(1,y-1,z-1));
return dp[x][y][z];
}
int main()
{
scanf("%d%d",&n,&m);
printf("%.9lf",dfs(1,n,m));
return 0;
}