zoukankan      html  css  js  c++  java
  • HDU4336 Card Collector DP求期望+状压

    题目大意:要集齐N张卡片,每包干脆面出现每种卡片的概率已知,问你集齐N张卡片所需要的方便面包数的数学期望(N<=20)。

    solution:

    由于N<=20,我们可以考虑状压,设dp[S]表示牌的状态为S时的需要的方便面包数的数学期望。

    那么,对于每一个状态,考虑枚举每一张牌i(摸到了i),此时:

    ① 如果S中不含i,dp[S]+=(dp[S|(1<<i-1)]+1)*p[i]。

    ② 如果S中已经包含i,那么算到下面的情况中去。

    但是注意到,上述情况是已经保证了摸到牌,但是其实可以没有摸到牌,结合②则dp[S]=(dp[S]+1)*P,其中P为摸不到任意一张牌或摸到一张已有的牌的概率,可以发现(P+sum{①中的p_i}=1)

    综上,得到(dp[S]=(dp[S]+1) *P+sum{_{!(S&(1<<i-1))}(dp[S|(1<<i-1)]+1) *p[i]}​)

    把式子整理一下,得到: (dp[s]=frac{1+sum{_{!(S&(1<<i-1)}}dp[S|(1<<i-1)*p[i]]}{1-P})

    Code:

    #include<cmath>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define RG register
    #define IL inline
    #define LL long long
    #define DB double
    using namespace std;
    
    const int N=1<<21;
    
    DB p0,p[21],dp[N];
    
    int main()
    {
    	RG int n,i,j,all;
    	while(scanf("%d",&n)!=EOF) {
    		all=(1<<n)-1;
    		memset(dp,0,sizeof(dp));
    		for(i=1;i<=n;++i) scanf("%lf",&p[i]);
    		for(i=all-1;i>=0;--i) {
    			for(j=1,p0=0;j<=n;++j)
    				if(!(i&(1<<j-1))) dp[i]+=dp[i|(1<<j-1)]*p[j],p0+=p[j];
    			dp[i]=(dp[i]+1)/p0;
    		}
    		printf("%.4lf
    ",dp[0]);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    A1083. List Grades
    A1075. PAT Judge
    uva 10054 The Necklace 欧拉回路
    uva 1423 / Guess
    poj3164 最小树形图
    uva 11865 stream my contest 最小树形图 朱刘算法
    uva 1494
    获取android源码中遇到的问题
    MTK平台Android项目APK预置方案
    Android Lights
  • 原文地址:https://www.cnblogs.com/Bhllx/p/10847660.html
Copyright © 2011-2022 走看看