POJ 2096 Collecting Bugs (概率dp)

来源:互联网 发布:奇热漫画软件 编辑:程序博客网 时间:2024/05/16 14:28

OJ题目 : click here ~~~

大概题意:

题目读起来有点累。有n个种类 , s个子系统 。每天找1个bug ,这个bug必属于某个种类和某个子系统,且概率相等,即为1/n , 1/s。给 n , s , 求找到属于n个种类 , s个系统的的bug,需要天数的期望。

定义dp[ i ][ j ] 为已找到属于 i 个种类 ,j个系统的bug , 距离目标还差的天数的期望。

有dp[ i ][ j ] ,找到下一个bug , 则,

1. 这个bug 属于已找到的 i 个种类别中的一个 , 且属于已找到的 j 个子系统中的一个 , 此时dp[ i ][ j ] , 概率为p1 = i/n * j / s;

2. 这个bug是新的1类 , 但属于已找到的j个子系统中的一个,此时dp[ i  +  1][ j ] , 概率为p2 = (1 -  i/n) * j / s;

3. 这个bug属于已经找到的i个类别中的一个 ,但是新的1个子系统 ,此时dp[ i ][ j + 1 ] , 概率为p3 = i/n *(1 - j / s);

4. 这个bug是新的1类,且是新的1个子系统,此时dp[ i + 1 ][ j + 1 ] , 概率为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;(找这个bug,需要一天,所以不能忘记加1)

不能将未知量当成已知使用 , so 整理方程,将dp[ i ][ j ]放在左边 ;

AC_CODE

double dp[1002][1002];int main(){    int n , s;    while(scanf("%d%d",&n,&s) != EOF)    {        int i , j;        double p1 , p2 , p3 , p4;        dp[n][s] = 0;        for(i = n;i >= 0;i--)        {            for(j = s;j >= 0;j--)            {                if(i == n&&j == s)                    continue;                p1 = (1.0 * i * j)/(n * s);                p2 = (n - i) * 1.0 * j/(n * s);                p3 = 1.0 * i * (s - j)/(n * s);                p4 = 1.0 * (n - i) * (s - j)/(n * s);                dp[i][j] = (p2 * dp[i + 1][j] + p3 * dp[i][j + 1] + p4 * dp[i + 1][j + 1] + 1)/(1 - p1);            }        }        printf("%.4lf\n",dp[0][0]);    }    return 0;}

0 0