**** **** 黑白球|DP

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

题解:

期望DP

\(f[i][j]\)是到达\(i\)黑球与\(j\)白球的期望。

则$ f[i][j]=(f[i-1][j+1] +1)* ... + (f[i-2][j+2]+1)*...+f[i][j] ...+ 1 *... $

移项得$ f[i][j](1-...)=(f[i-1][j+1] +1) ... + (f[i-2][j+2]+1)*...+ 1 *... $

\(f[i][j]=\frac{(f[i-1][j+1] +1)* ... + (f[i-2][j+2]+1)*...+ 1 *... }{1-...}\)

\(...\)的部分请自行思考

总结:

理清思路,一个正推反推调了两天。

据@info___tion,很多时候期望DP是往后(结果往起点)推的(?

代码

#include<bits/stdc++.h>
using namespace std;
int t,n,m;double f[100][100];bool vis[100][100];
void dfs(int i,int j)
{
	if (i>=n+m&&j<=0) return ;
	if (vis[i][j]) return ;
	vis[i][j]=true;
	dfs(i+1,j-1);
	dfs(i+2,j-2);
	if (j-1>=0) f[i][j]=(f[i+1][j-1]+1.0)*((j*1.0)/(n+m) * (i*1.0)/(n+m-1.0)  
			+ (i*1.0)/(n+m) * (j*1.0)/(n+m-1.0)) ;
	if (j-2>=0) f[i][j]+=(f[i+2][j-2]+1.0)* (j*1.0)/(n+m)*(j-1.0)/(n+m-1.0);
	f[i][j]=(f[i][j] )/ (1.0-1.0* i/(n+m)*(i-1.0)/(n+m-1))+(1.0*i*1.0/(n+m)*(i-1.0)/(n+m-1.0))/(1.0-i*1.0/(n+m)*(i-1.0)/(n+m-1.0));
}
int main()
{
	freopen("2829.in","r",stdin);
	freopen("2829.out","w",stdout);
	cin>>t;
	for (int tt=1;tt<=t;tt++)
	{
		cin>>n>>m;
		for (int i=0;i<=n+m;i++)
		  for (int j=0;j<=m;j++)
		    f[i][j]=0,vis[i][j]=0;
		dfs(n,m);
		printf("%.8lf\n",f[n][m]) ;
	}
	return 0;
}
posted @ 2019-03-27 14:13  fmj_123  阅读(205)  评论(0编辑  收藏  举报