poj2096 Collecting Bugs(概率和期望DP)

题目链接:https://cn.vjudge.net/contest/247409#problem/B

题目大意:

一个软件有s个子系统,会产生n种bug
某人一天发现一个bug,每个bug属于一个子系统,属于一个分类 
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
求发现n种bug,且每个子系统都发现了bug的天数的期望。

题目思路:

f[i][j]表示现在已经找到的bug有i种,属于j个系统,找完剩下所需bug的期望天数。
已知:f[n][s]=0, 而要求的答案是f[0][0]
每天有四种情况:
发现一个bug属于已经有的i个分类和j个系统。(i/n)*(j/s) * (f[i][j] +1)
发现一个bug属于已有的分类,不属于已有的系统。(i/n)*(1-j/s)  * (f[i][j+1]+1)
发现一个bug属于已有的系统,不属于已有的分类。 (1-i/n)*(j/s) * (f[i+1][j]+1)
发现一个bug不属于已有的系统,不属于已有的分类。 (1-i/n)*(1-j/s)  *(f[i+1][j+1]+1)
f[i][j] = (i/n)*(j/s) * (f[i][j] +1) + (i/n)*(1-j/s)  * (f[i][j+1]+1) + (1-i/n)*(j/s) * (f[i+1][j]+1) + (1-i/n)*(1-j/s)  *(f[i+1][j+1]+1)
最后因为左右两边都要f[i][j],化简一下即可

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string.h>
using namespace std;
const int maxn=1200;
/*dp[i][j] = (i/n)*(j/s) * (dp[i][j] +1) + (i/n)*(1-j/s)*(dp[i][j+1]+1)+
            (1-i/n)*(j/s)*(dp[i+1][j]+1)+(1-i/n)*(1-j/s)*(dp[i+1][j+1]+1)*/
int n,s;
double dp[maxn][maxn];
int main()
{
    while(~scanf("%d%d",&n,&s))
    {
        memset(dp,0,sizeof dp);
        for(int i=n;i>=0;i--)
        {
            for(int j=s;j>=0;j--)
            {
                if(i==n&&j==s)continue;
                dp[i][j]=(1.0*i/n)*(1.0*j/s)+1.0*(1.0*i/n)*(1-1.0*j/s)*(dp[i][j+1]+1)
                +(1-1.0*i/n)*(1.0*j/s)*(dp[i+1][j]+1)+(1-1.0*i/n)*(1-1.0*j/s)*(dp[i+1][j+1]+1);
                dp[i][j]=dp[i][j]/(1.0-(1.0*i/n)*(1.0*j/s));
            }
        }
        printf("%.4f\n",dp[0][0]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36782366/article/details/81739786