HDU 4336 Card Collector(状压 + 概率DP 期望)题解

Posted kirinsb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4336 Card Collector(状压 + 概率DP 期望)题解相关的知识,希望对你有一定的参考价值。

题意:每包干脆面可能开出卡或者什么都没有,一共n种卡,每种卡每包爆率pi,问收齐n种卡的期望

思路:期望求解公式为:$E(x) = \\sum_i=1^kpi * xi + (1 - \\sum_i = 1^kpi) * [1 + E(x)]$,即能转换到x情况的期望+x情况原地踏步的期望。

因为n比较小,我们可以直接状压来表示dp[x]为x状态时集齐的期望。那么显然dp[111111111] = 0。然后我们状态反向求解。最终答案为dp[0]。

然后来看期望的求解:$E(x) = \\sum_i = 1^kpi * [1 + E(xi)] + (1 - \\sum_i = 1^kpi) * [1 + E(x)]$,E(xi)是E(x)某一位0变成1后的期望。

化简后:$E(x) = (\\sum_i = 1^kpi * E(xi) + 1) / \\sum_i = 1^kpi$

题解

代码:

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 20 + 5;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;
double dp[1 << maxn];
double p[maxn];
int main()
    int n;
    while(~scanf("%d", &n))
//        for(int i = 0; i < (1 << n); i++) dp[i] = 0;
        for(int i = 0; i < n; i++)
            scanf("%lf", &p[i]);
        
        dp[(1 << n) - 1] = 0;
        for(int i = (1 << n) - 2; i >= 0; i--)
            double sump = 0, sumpe = 0;
            for(int j = 0; j < n; j++)
                if(!(i & (1 << j)))
                    sump += p[j];
                    sumpe += p[j] * dp[i | (1 << j)];
                
            
            dp[i] = (sumpe + 1) / sump;
        
        printf("%.6f\\n", dp[0]);
    
    return 0;

 

以上是关于HDU 4336 Card Collector(状压 + 概率DP 期望)题解的主要内容,如果未能解决你的问题,请参考以下文章

hdu 4336 Card Collector

hdu_4336_Card Collector

HDU 4336 Card Collector(状态压缩+概率DP)

hdu 4336 Card Collector——最值反演

HDU 4336 Card Collector

HDU4336Card Collector (动态规划,数学期望)