黑白球 概率 动态规划

黑白球

题目描述

一个箱子里面有n个黑球m个白球。你每小时都随机从箱子里面抽出两个小球,然后把这两个球都染成黑球,然后再放回去。问需要多少小时才能把所有小球变成黑色小球?输出期望值。

输入格式

多组测试数据。

第一行,一个整数G,表示有G组测试数据。1&lt;=G&lt;=101&lt;=G&lt;=101<=G<=10

每组测试数据格式如下:

一行,两个整数,n和m。1&lt;=n1 &lt;=n1<=n,m&lt;=47m&lt;=47m<=47

输出格式

共G行,每行一个实数。误差不能超过0.00001。

输入样例

5
1 1
2 1
1 2
4 7
1 3

输出样例

1.0
1.5
2.0
13.831068977298521
3.4

解题思路

题目大意:有黑白两种球,求将全部球染成黑球的操作次数期望值。

经过一段时间的思考,我们可以发现本题用动态规划解决是比较方便的,可以用二维的动态规划;因为题目中只有两种颜色的球,所以这里采用较方便的一维。

我们设f[i]f[i]f[i]表示盒子里有iii个黑球,还要多少小时才能变成n+mn+mn+m个黑球。很显然,白球数量就是n+m−in+m-in+mi个。

根据题意,我们要从最开始的nnn个黑球f[n]f[n]f[n]推到全部变为黑球f[n+m]f[n+m]f[n+m]

那么f[i]f[i]f[i]是怎么推来的呢?抽球的概率又怎么计算呢?


首先,我们分类讨论

对于第iii次操作:

  1. 抽到两个黑球
  2. 抽到两个白球
  3. 先抽到黑球,再抽到白球
  4. 先抽到白球,再抽到黑球

对于以上四种情况,我们有以下四条概率计算式:

  1. 抽到两个黑球的概率是:
    in+m×i−1n+m−1\frac{i}{n+m}\times\frac{i-1}{n+m-1}n+mi×n+m1i1
  2. 抽到两个白球的概率是:
    n+m−in+m×n+m−i−1n+m−1\frac{n+m-i}{n+m}\times\frac{n+m-i-1}{n+m-1}n+mn+mi×n+m1n+mi1
  3. 先抽到黑球,再抽到白球的概率是:
    in+m×n+m−in+m−1\frac{i}{n+m}\times\frac{n+m-i}{n+m-1}n+mi×n+m1n+mi
  4. 先抽到白球,再抽到黑球的概率是:
    n+m−in+m×in+m−1\frac{n+m-i}{n+m}\times\frac{i}{n+m-1}n+mn+mi×n+m1i

那么,对于第iii次操作,我们运用倒推的方法就可以将式子推出来了。

f[i]=1+f[i]×in+m×i−1n+m−1+f[i−2]×n+m−in+m×n+m−i−1n+m−1+f[i−1]×in+m×n+m−in+m−1+f[i−1]×n+m−in+m×in+m−1f[i]=1+f[i]\times\frac{i}{n+m}\times\frac{i-1}{n+m-1}+f[i-2]\times\frac{n+m-i}{n+m}\times\frac{n+m-i-1}{n+m-1}+f[i-1]\times\frac{i}{n+m}\times\frac{n+m-i}{n+m-1}+f[i-1]\times\frac{n+m-i}{n+m}\times\frac{i}{n+m-1}f[i]=1+f[i]×n+mi×n+m1i1+f[i2]×n+mn+mi×n+m1n+mi1+f[i1]×n+mi×n+m1n+mi+f[i1]×n+mn+mi×n+m1i


到了这一步,不知大家发现一个问题没有,f[i]f[i]f[i]在运算过程中,乘了一遍它自己,那么怎么解决这个问题呢?


利用数学知识:等式两边加一个相同的数,等式仍成立

我们不妨将f[i]×in+m×i−1n+m−1f[i]\times\frac{i}{n+m}\times\frac{i-1}{n+m-1}f[i]×n+mi×n+m1i1这一项移到左边去。

f[i]−f[i]×in+m×i−1n+m−1=1+f[i−2]×n+m−in+m×n+m−i−1n+m−1+f[i−1]×in+m×n+m−in+m−1+f[i−1]×n+m−in+m×in+m−1f[i]-f[i]\times\frac{i}{n+m}\times\frac{i-1}{n+m-1}=1+f[i-2]\times\frac{n+m-i}{n+m}\times\frac{n+m-i-1}{n+m-1}+f[i-1]\times\frac{i}{n+m}\times\frac{n+m-i}{n+m-1}+f[i-1]\times\frac{n+m-i}{n+m}\times\frac{i}{n+m-1}f[i]f[i]×n+mi×n+m1i1=1+f[i2]×n+mn+mi×n+m1n+mi1+f[i1]×n+mi×n+m1n+mi+f[i1]×n+mn+mi×n+m1i

(1−in+m×i−1n+m−1)×f[i]=1+f[i−2]×n+m−in+m×n+m−i−1n+m−1+f[i−1]×in+m×n+m−(i−1)n+m−1+f[i−1]×n+m−in+m×in+m−1(1-\frac{i}{n+m}\times\frac{i-1}{n+m-1})\times f[i]=1+f[i-2]\times\frac{n+m-i}{n+m}\times\frac{n+m-i-1}{n+m-1}+f[i-1]\times\frac{i}{n+m}\times\frac{n+m-(i-1)}{n+m-1}+f[i-1]\times\frac{n+m-i}{n+m}\times\frac{i}{n+m-1}(1n+mi×n+m1i1)×f[i]=1+f[i2]×n+mn+mi×n+m1n+mi1+f[i1]×n+mi×n+m1n+m(i1)+f[i1]×n+mn+mi×n+m1i

至此,再将(1−in+m×i−1n+m−1)(1-\frac{i}{n+m}\times\frac{i-1}{n+m-1})(1n+mi×n+m1i1)移回右边。

f[i]=1+f[i−2]×n+m−in+m×n+m−i−1n+m−1+f[i−1]×in+m×n+m−in+m−1+f[i−1]×n+m−in+m×in+m−1(1−in+m×i−1n+m−1)f[i]=\frac{1+f[i-2]\times\frac{n+m-i}{n+m}\times\frac{n+m-i-1}{n+m-1}+f[i-1]\times\frac{i}{n+m}\times\frac{n+m-i}{n+m-1}+f[i-1]\times\frac{n+m-i}{n+m}\times\frac{i}{n+m-1}}{(1-\frac{i}{n+m}\times\frac{i-1}{n+m-1})}f[i]=(1n+mi×n+m1i1)1+f[i2]×n+mn+mi×n+m1n+mi1+f[i1]×n+mi×n+m1n+mi+f[i1]×n+mn+mi×n+m1i

这就是最终的动态规划式子了


代码:

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值