HDU 4336 Card Collector (概率DP 或 容斥原理)

来源:互联网 发布:纳米材料就业知乎 编辑:程序博客网 时间:2024/05/22 12:33

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336


题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率为pi, 每包至多一张卡片,也可能没有卡片, 求需要买多少包才能拿全N张卡片,求次数的期望。


概率DP思路:可以状压枚举每个状态,然后状态间进行转移,注意对于发生状态转移的概率的理解:

如果当前状态能够从n种状态转移得来,则第i种发生的概率为pi/sum(p1....pn)


容斥原理:思路转自:http://m.blog.csdn.net/blog/c3568/9902141


如果一个事件发生的概率为p, 那么它第一次发生时的次数期望就是1/p

如果两个事件发生的概率分别为p1,p2, 那么第一次发生其中的某一件的次数期望就是1/(p1+p2)

以此类推进行容斥



#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;const int maxn = 21;double p[maxn];double dp[1 << maxn];int main(){    int n;    while (~scanf("%d", &n))    {        double t = 0;        for (int i = 0; i < n; i++)        {            scanf("%lf", &p[i]);            t += p[i];        }        t = 1 - t;        memset(dp, 0, sizeof(dp));        for (int i = (1 << n) - 2; i >= 0; i--)        {            double a = 0, sum = 1;            for (int j = 0; j < n; j++)            {                if (i & (1 << j))                    a += p[j];                else                    sum += dp[i | (1 << j)] * p[j];            }            dp[i] = sum / (1 - a - t);        }        printf("%.4f\n", dp[0]);    }    return 0;}


#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;const int maxn = 21;double p[maxn];int main(){    int n;    while (~scanf("%d", &n))    {        for (int i = 0; i < n; i++)            scanf("%lf", &p[i]);        double ans = 0;        for (int i = 1; i < (1 << n); i++)        {            double sum = 0;            int cnt = 0;            for (int j = 0; j < n; j++)            {                if (i & (1 << j))                {                    sum += p[j];                    cnt++;                }            }            if (cnt & 1)                ans += 1.0 / sum;            else                ans -= 1.0 / sum;        }        printf("%.4f\n", ans);    }    return 0;}


0 0
原创粉丝点击