1. 程式人生 > >期望dp-hdu-4336-Card Collector

期望dp-hdu-4336-Card Collector

題目連結:

題目大意:

有n種卡片,每包中至多有一種卡片,概率分別為p1,p2,...pn,可能有的沒有卡片,求包數的期望,使得每種卡片都有。

解題思路:

由於n最多隻有20,可以進行狀態壓縮。

dp[i]表示在狀態i獲得的卡片的情況下,得到最後結果所需的包數期望。

則dp[i]=no*(dp[i]+1)+∑pp[j]*(dp[i]+1)+∑pp[k]*(dp[i|(1<<k)]+1).

no:表示沒有卡片的概率,∑pp[j]表示第j種卡片已經存在,∑pp[k]表示第j種卡片當前還沒有。顯然no+∑pp[j]+∑pp[k]=1,所以花間得dp[i]=1+(no+∑pp[j])*dp[i]+∑pp[k]*dp[i|(1<<k)]

dp[1<<n-1]=0遞推求出dp[0]即可。

程式碼:

#include <iostream>
#include<cmath>
using namespace std;


double dp[1<<20],pp[25];

int main()
{
    int n;

    while(~scanf("%d",&n))
    {
        double no=0;

        for(int i=0;i<n;i++)
        {
            scanf("%lf",&pp[i]);
            no+=pp[i];
        }
        no=1-no;

        int lim=(1<<n)-1;
        dp[lim]=0;

        for(int i=lim-1;i>=0;i--)
        {
            dp[i]=1;
            double temp=0.0;
            for(int j=0;j<n;j++)
            {
                if(i&(1<<j))
                {
                    temp+=pp[j];
                    continue;
                }
                dp[i]+=dp[i|(1<<j)]*pp[j];
            }
            dp[i]/=(1-no-temp);
        }
        printf("%0.6f\n",dp[0]);
    }
    return 0;
}