POJ 2096 Collecting Bugs

Collecting Bugs

首個概率DP類題目。題意: 一個軟件有S個子系統,會產生n中bug

某人一天發現一個bug,這個bug屬於一個子系統並且屬於一個分類。每個bug屬於某個子系統的概率是1/s,屬於某個分類的概率爲1/n,求發現n中bug,每個子系統都發現bug的天數的期望。

全期望的公式:E(Y) = E(E(Y|x)) = sgm(P(X=xi)E(Y|X = xi)) ;粘貼公式不方便= =

設dp[i][j] 表示已經找到i種bug,j個子系統的bug,達到目標狀態的天數的期望,由於我們可以很容易確定最後的狀態,所以逆推。dp[n][s] = 0 ; 答案就是dp[0][0] ;

dp[i][j] 可以轉化爲如下狀態:

(1)如果發現的一個bug爲已有的i個分類和j個子系統,概率爲(i/n) * (j/s);

(2)如果發現的一個bug爲已有的分類,但不屬於已有系統,概率爲(i/n) * (1 - j/s) ;

(3)如果發現的一個bug不是已有的分類,但是已有的系統,概率爲(1- i/n) * (j/s) ;

(4)如果發現的一個bug既不是已有的分類,也不是已有的系統中的,概率爲(1 - i/n) * (1 - j/s) ;

然後我們就結合全期望公式整理就可以很容易得到轉移方程。代碼如下:

/*
    author    : csuchenan
    prog      : POJ 2096
    algorithm : probability DP 
    csuchenan	2096	Accepted	8068K	172MS	C++	651B	
*/
#include <cstdio>
#include <cstring>
const int maxn = 1005 ;

double dp[maxn][maxn] ;
int main(){
    int n , s ;
    scanf("%d%d" , &n , &s) ;
    dp[n][s] = 0 ;
    for(int i = n ; i >= 0 ; i --){
        for(int j = s ; j >= 0 ; j  --){
            if(i == n && j == s)
                continue ;
             dp[i][j] = (i * (s-j) * dp[i][j + 1]
                + (n - i) * j * dp[i + 1][j]
                + (n - i) * (s - j) * dp[i + 1][j + 1]
                + n * s )/(n * s - i * j) ;
        }
    }
    printf("%.4f\n" , dp[0][0]) ;
    return 0 ;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章