首页 > 代码库 > poj 2096 Collecting Bugs (概率dp)

poj 2096 Collecting Bugs (概率dp)

/*
dp求期望
逆着递推求解
题意:
   一个软件有s个子系统,会产生n种bug
   某人一天发现一个bug,这个bug属于一个子系统,属于一个分类
   每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
   问发现n种bug,每个子系统都发现bug的天数的期望。
求解:
    dp[i][j]表示已经找到i种bug,j个系统的bug,达到目标状态的天数的期望
    dp[n][s]=0,dp[0][0]为所求答案
    dp[i][j]由四种状态转化而来
    1:dp[i][j] 发现一个状态已有i个分类j个系统 概率p1=i/n*j/s
    2: dp[i+1][j]  发现有未属于这个分类,但属于这个系统的bug 概率p2=(1-i/n)*j/s
    3: dp[i][j+1] 发现属于这个系统,但不属于这个分类的bug 概率p3=i/n*(1-j/s)
    4: dp[i+1][j+1] 发现为属于这个系统且不属于这个分类的bug 概率p4=(1-i/n)*(1-j/s)

    所以:dp[i][j] = p1*dp[i][j] + p2*dp[i+1][j] + p3*dp[i][j+1] + p4*dp[i+1][j+1] + 1;
    化简得:
          dp[i][j]=(dp[i+1][j]*(n*j-i*j)+dp[i][j+1]*(i*s-i*j)+dp[i+1][j+1]*(n*s-j*n-i*s+i*j)+n*s)/(n*s-i*j);
*/
# include <stdio.h>
# include <algorithm>
# include <string.h>
# include <iostream>
using namespace std;
double dp[1010][1010];
int main()
{
    int n,s,i,j;
    while(~scanf("%d%d",&n,&s))
    {
        // memset(dp,0,sizeof(dp));
        dp[n][s]=0;
        for(i=n; i>=0; i--)
        {
            for(j=s; j>=0; j--)
            {
                if(i==n&&j==s)
                    continue;
                dp[i][j]=(dp[i+1][j]*(n*j-i*j)+dp[i][j+1]*(i*s-i*j)+dp[i+1][j+1]*(n*s-j*n-i*s+i*j)+n*s)/(n*s-i*j);
            }
        }
        printf("%.4lf\n",dp[0][0]);
    }
    return 0;
}

poj 2096 Collecting Bugs (概率dp)