题目翻译
原题 Bag of mice Code Forces - 148D
龙和公主在争论新年前夜该做什么。龙建议飞到山上去看仙女们在月光下跳舞,而公主认为他们应该早点睡觉。他们不顾一切地想要达成一个友好的协议,所以他们决定让这一切听天由命。
他们轮流从一个最初装有w只白色和b只黑色老鼠的袋子里抓出一只老鼠。第一个抓出白色老鼠的人赢了。在每只被龙抓的老鼠之后,袋子里的其他老鼠就会恐慌,其中一只会跳出袋子(公主小心地抓着她的老鼠,不去惊吓其他的老鼠)。公主了。公主获胜的概率是多少?
如果袋子里没有更多的老鼠,也没有人抓出一只白老鼠,龙就赢了。从袋子里跳出来的老鼠不被认为是被抓走的(不确定获胜者)。一旦老鼠离开了袋子,它就再也不回来了。每只老鼠从袋子里出来的概率和其他老鼠是一样的,每只老鼠从袋子里跳出来的概率和其他老鼠是一样的。
输入
输入数据的唯一一行包含两个整数w和b(0≤w, b≤1000)。
输出
输出公主获胜的概率。如果答案的绝对或相对误差不超过1e - 9时,则认为是正确的。
例子
输入
1 3
输出
0.500000000
输入
5 5
输出
0.658730159
请注意
我们来看第一个例子。公主在第一轮抓到一只小白鼠并立即获胜的概率是1/4。龙抓到黑老鼠,第一轮没有赢的概率是3/4 * 2/3 = 1/2。在这之后,袋子里还剩下两只老鼠——一只黑的,一只白的;其中一个跳了出来,另一个在第二轮被公主抓出。如果公主的老鼠是白色的,她就赢了(概率是1/2 * 1/2 = 1/4),否则没有人得到白色的老鼠,所以根据规则,龙赢了。
思路
概率dp
用 dp[ i ][ j ] 来表示在有 i 只白老鼠,j 只黑老鼠的时候公主获胜的概率。
1.公主第一次就抓到了白老鼠,公主获胜。概率为 i / (i+j) ;
2.公主第一次抓到了黑老鼠,龙第一次抓到了白老鼠,龙获胜。概率为 j/(i+j)*i/(i+j-1);
3.公主抓一次黑老鼠,龙抓一只黑老鼠,袋子里会跳出一只老鼠:
(1) 当跳出的老鼠是白老鼠时,概率为 j/(i+j) * (j-1)/(i+j-1) * i /(i+j-2) ; 这种情况袋子里至少有两只黑老鼠(j>=2)
(2) 当跳出的老鼠是黑老鼠时,概率为 j/(i+j) * (j-1)/(i+j-1) * (j-2)/(i+j-2) ; 这种情况袋子里至少有三只黑老鼠(j>=3)
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
double dp[2020][2020];
int main()
{
int w,b;
while(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];
}
}
printf("%.9lf\n",dp[w][b]);
}
}