SMOJ 2829 黑白球|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;
}

猜你喜欢

转载自www.cnblogs.com/fmj123/p/SMOJ2829.html