POJ 2096 Collecting Bugs 概率dp+期望

版权声明:转载请注明出处 https://blog.csdn.net/jay__bryant/article/details/81745477

题目大意:bug由有s个子系统产生,属于n种分类。且由每个子系统产生的概率是1/s,属于某种分类的概率是1/n。每天发现一个bug,求每个子系统都产生了bug且n种bug都有的期望天数。

概率dp的状态设置都挺套路:当前状态是…且要达到目标状态的期望值
dp[i][j]:当前状态是已有i种分类,j个子系统产生了bug。
边界:dp[n][s] = 0。
dp[0][0]为所求
状态转移:将每种情况的期望相加即可
(1)发现一个bug属于已经有的i个分类和j个系统::(i/n)(j/s)(dp[i][j]+1);
(2)发现一个bug属于已有的分类,不属于已有的系统:(i/n)(1-j/s)(dp[i][j+1]+1)
(3)发现一个bug属于已有的系统,不属于已有的分类:(1-i/n)(j/s)(dp[i+1][j]+1)
(4)发现一个bug不属于已有的系统,不属于已有的分类:(1-i/n)(1-j/s)(dp[i+1][j+1]+1)

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)

#include <cstdio>
#include <cstring>

using namespace std;
const int N = 1010;
double dp[N][N];
int n, s;

int main()
{
    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;
            double f1 = (1.0*i/n)*(1-1.0*j/s)*(dp[i][j+1]+1);
            double f2 = (1-1.0*i/n)*(1.0*j/s)*(dp[i+1][j]+1);
            double f3 = (1-1.0*i/n)*(1-1.0*j/s)*(dp[i+1][j+1]+1);
            double t = (1.0*i/n)*(1.0*j/s);
            dp[i][j] = (f1+f2+f3+t)/(1.0-t);
        }
    printf("%.4f\n", dp[0][0]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/81745477