zoukankan      html  css  js  c++  java
  • [HDU 4336]Card Collection[状态压缩DP][概率DP][容斥原理]

    题意:

    小吃中有N种卡片,每种卡片 i 出现的概率为 pi ,一袋小吃有可能没有卡片,但最多有一张.问集齐所有卡片需要购买小吃的袋数期望.

    思路:

    1.用状压dp,dp[ s ]表示在s状态时,集齐所需要的袋数期望.

    s = 11111表示N = 5时集齐的状态,此时dp[ s ] = 0;

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

    因为"期望"是

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

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

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

    //281MS	8480K
    #include<cstdio>
    using namespace std;
    const int MAXN=22;
    double p[MAXN];
    double dp[1<<MAXN];
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            double tt=0;
            for(int i=0;i<n;i++)
            {
                scanf("%lf",&p[i]);
                tt+=p[i];
            }
            tt=1-tt;//tt就表示没有卡片的概率了
            dp[(1<<n)-1]=0;//全部收集到了就不需要再买了.求期望一般都是反着推.
            for(int i=(1<<n)-2;i>=0;i--)//遍历所有方案
            {
                double x=0,sum=1;///肯定要拿自己那一张卡片
                for(int j=0;j<n;j++)
                {
                    if((i&(1<<j)))x+=p[j];///如果此种卡片在i中已经存在,累加其概率
                    else sum+=p[j]*dp[i|(1<<j)];///若不存在,说明可以由此种情况转化而来
    ///dp[i|(1<<j)]是"确定事件",p[j]是该确定事件发生的概率,相乘则表示期望.
                }
                dp[i]=sum/(1-tt-x);
            }
            printf("%.5lf
    ",dp[0]);
    
        }
        return 0;
    }

    自己敲一遍:

    //250MS  8480K
    #include<cstdio>
    using namespace std;
    const int MAXN = 22;
    double p[MAXN],dp[1<<MAXN];
    int main()
    {
        int N,m;
        while(scanf("%d",&N)==1)
        {
            for(int i=0;i<N;i++)
                scanf("%lf",p+i);
            m = 1 << N ;
            dp[m-1] = 0;
            for(int i=m-2;i>=0;i--)
            {
                double sump = 0,sum = 1;
                for(int j=0;j<N;j++)
                {
                    if(!(i & (1<<j)))//位运算写成了逻辑与...手残
                    {
                        sump += p[j];//有用的概率
                        sum += p[j]*dp[i|(1<<j)];
                    }
                }
                dp[i] = sum / sump;
            }
            printf("%.5lf
    ",dp[0]);///虽然样例中输出是保留了3位,但是题中描述是误差1e-4的...所以...
        }
    }

    2.容斥原理(先记下,稍后学习...)

    //421MS	340K
    #include<iostream>
    #include<cstdio>
    using namespace std;
    double s;  int n,vis[25];
    double a[25];
    void dfs(int k,double sum,int cou,int j){
        if(cou==k){
            s+=1/sum;
            return ;
        }
        for(int i=j;i<=n;i++){
                sum+=a[i];
                cou++;
                dfs(k,sum,cou,i+1);
                cou--;
                sum-=a[i];
        }
        return ;
    }
    int main(){
        while(~scanf("%d",&n)){
            for(int i=1;i<=n;i++){
                scanf("%lf",&a[i]);
            }
            double sum=0;
            for(int i=1;i<=n;i++)
                sum+=(1/a[i]);
            for(int i=2;i<=n;i++){
                s=0;
                dfs(i,0,0,1);
                if(i%2==0) sum+=(-1)*s;
                else sum+=s;
            }
            printf("%lf
    ",sum);
        }
    }
    /*
    HDU 4336
    容斥原理
    位元素枚举
    */
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    double p[22];
    int main()
    {
        int n;
        while(scanf("%d",&n)==1)
        {
            for(int i=0;i<n;i++)scanf("%lf",&p[i]);
            double ans=0;
            for(int i=1;i<(1<<n);i++)
            {
                int cnt=0;
                double sum=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("%.5lf
    ",ans);
        }
        return 0;
    }
    
    


  • 相关阅读:
    这难道就是一个普通人的一生???
    【纪念】纪念随笔数上3位数
    【移动端】js禁止页面滑动与允许滑动
    【react懒加载组件】--react-lazyload
    ES6知识整理(7)--Set和Map数据结构
    Hibernate检索策略
    Hibernate HQL多表查询
    Hibernate各种查询操作(二)
    Hibernate各种查询操作(一)
    Hibernate多对多操作
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3260450.html
Copyright © 2011-2022 走看看