zoukankan      html  css  js  c++  java
  • HDU 4336 Card Collector 期望dp+状压

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4336

    Card Collector

    Time Limit: 2000/1000 MS (Java/Others)
    Memory Limit: 32768/32768 K (Java/Others)
    #### 问题描述 > 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.

    输入

    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 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.

    样例输入

    1
    0.1
    2
    0.1 0.4

    样例输出

    10.000
    10.500

    题意

    小时候买零食的时候,里面都会附带一张卡片(或没有),现在告诉你每包零食里面每一种卡片出现的概率,问你集齐这n类卡片需要买的零食的期望包数。

    题解

    由于卡片种类最多就20多种,所以状压一下从dp[(1<<n)-1]地推到dp[0]就可以了。
    dp[i]表示已经集齐状态为i的卡片,平均还要买多少包才能集齐所有的。
    转移方程:dp[i]=(1-sp)*dp[i]+sigma(pro[j]*dp[i^(1<<j)])+1(这里要保证i&(1<<j)==0,并且sp=sigma(pro[j]).)
    移项得:dp[i]=sigma(pro[j]*dp[i^(1<<j)]+1)/(1-(1-sp))

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef __int64 LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-9;
    
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    double dp[1<<21];
    
    double pro[22];
    int n;
    
    int main() {
        while(scf("%d",&n)==1&&n){
            rep(i,0,n){
                scf("%lf",&pro[i]);
            }
            dp[(1<<n)-1]=0.0;
            for(int i=(1<<n)-2;i>=0;i--){
                dp[i]=0;
                double sp=0;
                for(int j=0;j<n;j++){
                    if(i&(1<<j)) continue;
                    sp+=pro[j];
                    dp[i]+=pro[j]*dp[i^(1<<j)];
                }
                dp[i]+=1;
                dp[i]/=sp;
            }
            prf("%.5lf
    ",dp[0]);
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
    

    容斥也可以做:

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef __int64 LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-9;
    
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    double pro[22];
    int n;
    
    int main() {
        while(scf("%d",&n)==1&&n){
            rep(i,0,n){
                scf("%lf",&pro[i]);
            }
    
            double ans=0;
            for(int i=1;i<(1<<n);i++){
                double sp=0;
                int cnt=0;
                for(int j=0;j<n;j++){
                    if(i&(1<<j)){
                        sp+=pro[j];
                        cnt++;
                    }
                }
                if(cnt%2) ans+=1.0/sp;
                else ans-=1.0/sp;
            }
    
            prf("%.5lf
    ",ans);
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    linux系统基本目录的介绍
    vue 组件之间的通信-父组件给子组件传递数据
    postgresql数据库查询特定日期的数据
    使用HttpRequest调用第三方接口
    postgresql数据库中的 rownum
    mybatis框架,执行插入语句的时候,如果没有字段传过来就赋值为空 进行判断
    postgresql数据库left join将主表中的数据查询出多条的解决办法
    前后端交互 -精度丢失问题解决
    vue找页面
    mysql语法 join on 表示什么
  • 原文地址:https://www.cnblogs.com/fenice/p/5973410.html
Copyright © 2011-2022 走看看