hdu 4336 概率DP 狀壓DP

/*
    概率DP  狀壓DP  條件期望DP  好題


    題意:有n種卡片,一袋面裏有一張卡片或者沒有。給出每種卡片出現在一袋面裏的概率,問要收集完n種卡片所需要買的袋面數目的期望(n <= 20).


    思路:狀壓表當前已收集到的卡片的狀態,位爲1表收集到了,0表沒有收集到。
          對於狀態T,考慮最近買的那袋面之前的狀態S(也就是狀態X在買了這袋面之後變成了狀態T),
            <1>這袋面沒有卡片
            <2>這袋面的卡片X已經收集過了
            <3>這袋面的卡片X還沒有收集過
    方法1: 
          前兩種情況新舊狀態不變,即T = S;後面一種情況S = T ^ (1<<k)
          則T數學期望E(T) = 1 + (1 - Σp[i])*E(T) + Σ(p[j]*E(T)) + Σ(p[k]*E(S))
          其中:i = 0, 1, 2,...n-1
                j = 第j種卡片已經收集過了,S & (1<<j) == 1
                k = 第k種卡片還沒有收集過,S & (1<<j) == 0
               
          移項可得:E(T) * Σp[k] = 1 + Σ(p[k] * E(S)    ,這裏的k=第k種卡片沒收集到,S = T ^ (1<<k)


          ps:我之前一直很奇怪爲什麼大家的代碼沒有對“袋面裏可能沒有卡片”這一點做處理,後來實在上面的移項過程種想明白的,移項的時候可以把情況<1>和<2>歸到一起。我纔想明白,其實袋子是否有可能爲空並不影響做題,我們可以把空袋子當作一張“隱形卡”,每個狀態都默認已經有了這張卡,所以情況<1>可以直接歸爲情況2,因爲不存在空的情況了,隱形卡大家已經收集過了。 




 ===================================================================================================================
 
    方法2:
          其實上述式子可以由條件期望的原理很容易地得出...
          
          首先 E(X|Y=y) =  Σxf(x|y)
               E(E(X|Y)) = EX,  我們叫EX爲全體加權平均,E(X|Y)爲條件加權平均(局部加權平均),在這道題裏X != Y


          這樣,我們就可以直接得出上述的公式了:
              E(X|Y)/Σpy = EX  
              Σ(E(Y)*py) / Σpy = EX


          其實條件期望我也是暈暈忽忽的,詳細看:http://blog.csdn.net/henhen2002/article/details/5540039
*/
#include <stdio.h>
#define     MAXN    25
double p[MAXN], f[1 << MAXN];
int n;
int main()
{
    while(scanf("%d", &n) != EOF) {
        for(int i = 0; i < n; i++) scanf("%lf", &p[i]);
        f[0] = 0;
        int top = (1 << n);
        for(int u = 1; u < top; u++) {
            double sum = 0, tmp = 0;
            sum += 1;
            for(int i = 0; i < n; i++) if(u & (1 << i)) {
                sum += f[u ^ (1 << i)] * p[i];
                tmp += p[i];
            }
            f[u] = sum/tmp;
        }
        printf("%f\n", f[top-1]);
    }
    return 0;
}


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