HDU 4336 Card Collector (概率-期望DP)【模板】

来源:互联网 发布:百度云的域名怎么转发 编辑:程序博客网 时间:2024/05/17 10:40

先解释一下期望值得定义,个人觉得比较难理解,跟以前书上了解的不太一样。

求期望的题,对于dp的定义一般都是从终态转移到初态,也就是反着求.

因为"期望"是

确定事件的结果 * 该事件发生的概率 = 平均来看尝试一次可以得到的结果,即期望

若是在s1状态得到一张卡片转移到了s2,那么s2是一个确定的状态,而在s1时则有多种可能性.由此可以理解反着求的合理性.

终态是初态的"去向",确是期望的"来源".


 下面来看题:

In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award. 

As a smart boy, you notice that to win the award, you must buy much more snacks than it seems to be. To convince your friends not to waste money any more, you should find the expected number of snacks one should buy to collect a full suit of cards.
Input
The first line of each test case contains one integer N (1 <= N <= 20), indicating the number of different cards you need the collect. The second line contains N numbers p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), indicating the possibility of each card to appear in a bag of snacks. 

Note there is at most one card in a bag of snacks. And it is possible that there is nothing in the bag.
Output
Output one number for each test case, indicating the expected number of bags to buy to collect all the N different cards. 

You will get accepted if the difference between your answer and the standard answer is no more that 10^-4.
Sample Input
10.120.1 0.4
Sample Output
10.00010.500

 【题解】

 好好来说一下这个题,网上给的解释看的我好费神,理解了好久。

 这题和以前的题不一样的地方是抽出每张卡片的概率都不一样,这样就不能用dp[i]来表示i的期望值,因为有n张卡片,所以要用二进制表示的1<<n种状态来表示每种状态到抽齐所有卡片需要的期望数,0表示还没抽出来,1表示已经抽到了。

 那么从后往前推,已知最后一种状态dp[(1<<n)-1]=0,因为这时候已经集齐了,往前遍历,前一种状态dp[(1<<n)-2]转移到最后一种状态需要的袋数期望值就是当前状态为0是位置的概率乘抽到该卡片后的袋数期望值。

这就是状态转移了,具体看代码:

【AC代码】

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=20;int n;double dp[1<<N];double p[N];int main(){    while(~scanf("%d",&n))    {        double pp=0;        for(int i=0;i<n;++i){            scanf("%lf",&p[i]);            pp+=p[i];        }        pp=1-pp;//抽不到卡片的概率        dp[(1<<n)-1]=0;//最终状态为1111...1时需要买的期望数是0        for(int i=(1<<n)-2;i>=0;--i)//遍历所有状态        {            double x=0;            double s=1;//先买一包  至于里面有什么卡片或者没有卡片就要分情况了            for(int j=0;j<n;++j)//遍历所有卡片类型            {                if(i&(1<<j))/*如果该卡片已经开出来了*/  x+=p[j]; //则把这部分的概率累加一下                else s+=p[j]*dp[i|(1<<j)];//如果该卡片第一次开出来,那么就准备状态转移,凡是没开出来的(0)状态位置都可以转移,把转移到每个位置的期望都加起来            } //简单点讲,就是比如现在二进制状态是101101,那么把当前的1放到第一个0位置处的期望就是0处的概率p[i]*把0换成1后的期望            dp[i]=s/(1-pp-x);//总的期望值除以抽到未开出卡片的概率就是期望值        }        printf("%.4f\n",dp[0]);//推到初始状态;    }    return 0;}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 4周岁宝宝拉肚子怎么办 小孩不肯拉小便怎么办 做销售不爱说话怎么办 我伤害了朋友怎么办 三岁发音不准怎么办 心里憋不住话怎么办 自己不长记性怎么办 孩子不愿意开口说话怎么办 孩子不爱开口说话怎么办 宝宝犟脾气不好怎么办 小孩说话不算话怎么办 孩子说话不算话怎么办 孩子故意不好好说话怎么办 小孩说话吐字不清楚怎么办 腿老是抽筋是怎么办 半夜睡觉脚抽筋怎么办 我不爱说话内向怎么办 小孩子吐字不清怎么办 宝宝前边头发少怎么办 宝宝咬嘴唇龅牙怎么办 小孩老是咬下唇怎么办 五月小孩掉下床怎么办 小孩说话夹舌头怎么办 小孩自闭不说话怎么办 孩子突然不说话怎么办 孩子说话语速慢怎么办 做磁共振不睡觉怎么办 宝宝吃饭不多怎么办 孩子吃饭爱说话怎么办 孩子吃饭喜欢说话怎么办 小孩子讲话嘴巴歪怎么办 小孩有自闭倾向怎么办 小孩笨反应慢怎么办 2岁不会说话怎么办 老公冷战不说话怎么办 小孩个子不高怎么办 额头发际线不齐怎么办 婴儿睡眠时间少怎么办 智商低不会说话怎么办 说话老是喷口水怎么办 数胎动宝宝不动怎么办