poj 2096 Collecting Bugs

题目链接:poj 2096 Collecting Bugs  


这道题目,网上找的做法都是一样的,感觉都没有很好的讲述为什么这么做是对的,而其他的就不行

这是本人第一道概率dp题目,随便yy的,难免错误,如果看到错误的话,万望指出

题意:

  1.  软件有s个子系统,会产生n种bug。 
  2.     某人一天发现一个bug,这个bug属于某种bug,发生在某个子系统中,都是等可能的情况
  3.     求找到所有的n种bug,且每个子系统都找到bug,这样所要的天数的期望。
每天bug 的可能情况是 n*s,每种对应的概率就是 1 / (n*s)


很容易想到的是状态是:dp[ i ][ j ] 表示 发生了i种bug ,j 个子系统的期望,如果当前是dp[ i ][ j ] 那么很容易 转移到的状态是:

   dp[ i ][ j ]               p1 = i*i/(n*s)

   dp[ i+1 ][ j ]          p2= (n-i)*j/(n*s)

   dp[ i ][ j +1 ]         p3=i*(s-j)/(n*s)

   dp[i +1][ j + 1]     p4=(n-i)*(s-j)/(n*s)


再仔细分析的话,发现 状态表示 dp[ i ][ j ] 的状态表示是错误的,例如:第一天dp[ 1 ][ 1 ]  = 1 , 那么第二天dp[ 1 ][ 1 ]呢?反正期望肯定会变多,期望本身的定义就是无穷 , 如果在加入一维 表示天数的话,几乎不可能……

如果我们逆着推,dp[i][j]表示已经找到i种bug,并存在于j个子系统中,要达到目标状态的天数的期望。很明显 dp[ n ][ s ] =0,  这样我们就算的每个dp[ i ][ j ] 就是最终答案了,不会随着天数的改变而改变了


dp[i,j] = p1*dp[i,j] + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] + (p1*1 +p2*1 +p3*1 + p4*1);   由于 p1 + p2 + p3 +p4  == 1

也就是 dp[i,j] = p1*dp[i,j] + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] + 1;

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

double dp[1010][1010];

int main()
{
    int n,s;
    while(scanf("%d%d",&n,&s)==2)
    {
       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 p1=i*j*1.0/(n*s);
           double p2=(n-i)*j*1.0/(n*s);
           double p3=i*(s-j)*1.0/(n*s);
           double p4=(n-i)*(s-j)*1.0/(n*s);
           dp[i][j]=(p2*dp[i+1][j]+p3*dp[i][j+1]+p4*dp[i+1][j+1]+1)/(1-p1);
       }
       //cout<<dp[1][1]<<endl;
       printf("%.4f\n",dp[0][0]);
    }
    return 0;
}



你可能感兴趣的:(poj 2096 Collecting Bugs)