poj 2096 Collecting Bugs (概率dp)

小记:dp好像分好多种,看到了斜率dp,概率dp,树形dp,。。。今天遇到了一个概率dp题,不晓得怎么入手。然后百度之,原来是概率dp,瞬间觉得好高端,看也看不懂,于是想着看能找点入门题做下。从网上找了一道,就是此题了。。。


题目大意:有一个程序,有n种bug和m个子系统,当找到一个bug时,它只会在一个系统。当然也可能你在其它系统也可以找到这样的bug,但是那是在找到另一个bug的时候,虽然两个是一种。规定一天只会找到一个bug。问,找到n种bug,且分布在m个子系统中的期望天数。


题解:因为每天都有一个,所以bug是无穷多个的。因此,每天找到一个bug它是某种类型的概率是1/n,在某个系统找到的概率是1/m。

令dp[i][j] 表示为找到了i种bug,分布在j个子系统中时,要到到目标状态所需要的期望天数。

很显然dp[n][m] = 0,而dp[0][0]就是我们要求的目标状态。

当我们找到了一个bug时,有四种情况可能出现;

dp[i][j],这个bug是原来i种就有的,且也在原来的j个子系统中

dp[i+1][j] ,这个bug是原来i种里所没有的,但在原来的j个子系统中

dp[i][j+1],这个bug在原来的i种就有的,但不在原来的j个子系统中

dp[i+1][j+1],这个bug是原来i种里所没有的,但也不在原来的j个子系统中

每一种发生的概率为:

p1 = i*j/(n*m)

p2 = (n-i)*j/(n*m)

p3 = i*(m-j)/(n*m)

p4 = (n-i)*(m-j)/(n*m)

根据期望的性质(在里面相加等于在各个分别期望相加),可得

dp[i,j] = p1*dp[i,j] + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] + 1

        = ( 1 + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] )/( 1-p1 ) 

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


代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <cstring>
using namespace std;

const int MAX_ = 1010;

double dp[MAX_][MAX_];

int main() {
    int n,m;
    while(~scanf("%d%d",&n,&m)) {
        dp[n][m] = 0.0;
        for(int i = n; i >= 0; i--){
            for(int j = m; j >= 0; j--){
                if(i == n && j== m)continue;
                dp[i][j] = (n*m + (n-i)*j*dp[i+1][j] +
                                i * (m-j) *dp[i][j+1] +
                                (n-i) * (m- j) *dp[i+1][j+1])/(n*m -i*j);
            }
        }
        printf("%.4lf\n",dp[0][0]);
    }
    return 0;
}



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