黑白球
zhongqijun · · 个人记录
黑白球
题目描述
一个箱子里面有n个黑球m个白球。你每小时都随机从箱子里面抽出两个小球,然后把这两个球都染成黑球,然后再放回去。问需要多少小时才能把所有小球变成黑色小球?输出期望值。
输入格式
多组测试数据。
第一行,一个整数G,表示有G组测试数据。
每组测试数据格式如下:
一行,两个整数,n和m。
输出格式
共G行,每行一个实数。误差不能超过0.00001。
输入样例
5
1 1
2 1
1 2
4 7
1 3
输出样例
1.0
1.5
2.0
13.831068977298521
3.4
解题思路
题目大意:有黑白两种球,求将全部球染成黑球的操作次数期望值。
经过一段时间的思考,我们可以发现本题用动态规划解决是比较方便的,可以用二维的动态规划;因为题目中只有两种颜色的球,所以这里采用较方便的一维。
我们设
根据题意,我们要从最开始的
那么
首先,我们分类讨论:
对于第
- 抽到两个黑球
- 抽到两个白球
- 先抽到黑球,再抽到白球
- 先抽到白球,再抽到黑球
对于以上四种情况,我们有以下四条概率计算式:
- 抽到两个黑球的概率是:
\frac{i}{n+m}\times\frac{i-1}{n+m-1} - 抽到两个白球的概率是:
\frac{n+m-i}{n+m}\times\frac{n+m-i-1}{n+m-1} - 先抽到黑球,再抽到白球的概率是:
\frac{i}{n+m}\times\frac{n+m-(i-1)}{n+m-1} - 先抽到白球,再抽到黑球的概率是:
\frac{n+m-i}{n+m}\times\frac{i}{n+m-1}
那么,对于第
到了这一步,不知大家发现一个问题没有,
利用数学知识:等式两边加一个相同的数,等式仍成立
我们不妨将
至此,再将
这就是最终的动态规划式子了
代码:
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,G;
double f[255],p1,p2,p3;
int main()
{
freopen("2829.in","r",stdin);
freopen("2829.out","w",stdout);
cin>>G;
for(int gr=1;gr<=G;gr++)
{
cin>>n>>m;
f[n+m+1]=f[n+m]=0.0;
for(int i=n+m-1;i>=n;i--)//倒推
{
//f[i]:当前有i个黑球,还要多少个小时才能变成n+m个黑球
//操作一次得到三种情况,转移到相应的子问题
p1=(double(i)/double(n+m))*(double(i-1)/double(n+m-1));//两个黑球
p2=(double(n+m-i)/double(n+m))*(double(n+m-1-i)/double(n+m-1));//两个白球
p3=(double(i)/double(n+m))*(double(n+m-i)/double(n+m-1));//先摸到黑球后摸到白球
p3+=(double(n+m-i)/double(n+m))*(double(i)/double(n+m-1));//先摸到白球后摸到黑球
f[i]=(p2*f[i+2]+p3*f[i+1]+1.00)/(1.00-p1);
}
printf("%.6lf\n",f[n]);
}
return 0;
}