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

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

    转自http://www.cnblogs.com/zhj5chengfeng/archive/2013/03/02/2939601.html

    做法分析


    由于卡片最多只有 20 种,使用状态压缩,用 0 表示这种卡片没有收集到, 1 表示这种卡片收集到了

    令:f[s] 表示已经集齐的卡片种类的状态的情况下,收集完所有卡片需要买东西次数的期望

    买一次东西,包装袋中可能:

            1. 没有卡片

            2. 卡片是已经收集到的

            3. 卡片是没有收集到的

    于是有:

            f[s] = 1 + ((1-segma{ p[i] })f[s]) + (segma{ p[j]*f[s] }) + (segma{ p[k]*f[s|(1<<k)] })

            其中:    i=0,2,...,n-1

                          j=第 j 种卡片已经收集到了,即 s 从右往左数第 j 位是 1:s&(1<<j)!=0

                          k=第 k 种卡片没有收集到,即 s 从右往左数第 k 位是 0:s&(1<<k)==0

    移项可得:

            segma{ p[i] }f[s] = 1 + segma{ p[i]*f[s|(1<<i) },i=第i 种卡片没有收集到

    目标状态是:f[0]

    /************************************************
    * Author        :Powatr
    * Created Time  :2015-8-25 18:21:57
    * File Name     :hdu4336.cpp
     ************************************************/
    
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    typedef long long ll;
    const int MAXN = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    
    double dp[1<<21];
    double a[21];
    int main(){
        int n;
        while(~scanf("%d", &n)){
            for(int i = 0; i < n; i++)
                scanf("%lf", &a[i]);
            memset(dp, 0, sizeof(dp));
            int maxn = (1 << n) - 1;
            dp[maxn] = 0;
            for(int i = maxn - 1; i >= 0; i--){
                double sum = 0;
                dp[i] = 1;
                for(int j = 0; j < n; j++){
                    if(i & (1 << j)) continue;
                    dp[i] += dp[i|(1<<j)]*a[j];
                    sum += a[j];
                }
                dp[i] /= sum;
            }
            printf("%f
    ", dp[0]);
        }
        return 0;
    }
                
    

      

  • 相关阅读:
    week4:周测错题
    小程序1:登录/注册小程序
    小程序2:实现一个购物车
    day26:装饰器&面向对象当中的方法&property
    day25:7个魔术方法&5个关于类的魔术属性
    day24:多态&魔术方法__new__&单态模式
    day23:单继承&多继承&菱形继承&__init__魔术方法
    day22:面向对象封装对象操作&类操作&面向对象删除操作
    day21:正则函数&模块和包(import)
    APP探索之iAPP
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4758311.html
Copyright © 2011-2022 走看看