• HDU 4336 Card Collector:状压 + 期望dp


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336

    题意:

      有n种卡片(n <= 20)。

      对于每一包方便面,里面有卡片i的概率为p[i],可以没有卡片。

      问你集齐n种卡片所买方便面数量的期望。

    题解:

      状态压缩。

      第i位表示手上有没有卡片i。

      表示状态:

        dp[state] = expectation

        (卡片状态为state时,要集齐卡片还要买的方便面数的期望)

      找出答案:

        ans = dp[0]

        刚开始一张卡片都没有。

      如何转移:

        now: dp[state]

        对于卡片i,如果手上已经有了i,则方便面里有i等价于面里什么都没有。

        所以子期望共两种:

          (1)拿到一张还没有的卡片i。

          (2)拿到垃圾2333。

        dp[state] = sigma( dp[state|(1<<i)] * p[i] ) + dp[state] * P(useless) + 1

        P(useless)为拿到垃圾的概率。

        设tot = sigma(p[i])

        P(useless) = 1 - tot

        原式移项后:

          dp[state] = ( sigma( dp[state|(1<<i)] * p[i] ) + 1 ) / tot

      边界条件:

        dp[(1<<n)-1] = 0

        已经集齐,不用再买。

    AC Code:

     1 // state expression:
     2 // dp[state] = expectation
     3 // state: state of present cards
     4 //
     5 // find the answer:
     6 // ans = dp[0]
     7 //
     8 // transferring:
     9 // now: dp[state]
    10 // dp[state] = sigma( dp[state|(1<<i)] * p[i] ) + dp[state] * P(useless) + 1
    11 // i: not been collected
    12 // dp[state] = ( sigma( dp[state|(1<<i)] * p[i] ) + 1 ) / (1 - P(useless))
    13 // dp[state] = ( sigma( dp[state|(1<<i)] * p[i] ) + 1 ) / tot
    14 //
    15 // boundary:
    16 // dp[(1<<n)-1] = 0
    17 #include <iostream>
    18 #include <stdio.h>
    19 #include <string.h>
    20 #define MAX_N 25
    21 #define MAX_S ((1<<20)+5)
    22 
    23 using namespace std;
    24 
    25 int n;
    26 double p[MAX_N];
    27 double dp[MAX_S];
    28 
    29 void read()
    30 {
    31     for(int i=0;i<n;i++)
    32     {
    33         cin>>p[i];
    34     }
    35 }
    36 
    37 void solve()
    38 {
    39     memset(dp,0,sizeof(dp));
    40     for(int state=(1<<n)-2;state>=0;state--)
    41     {
    42         double tot=0;
    43         for(int i=0;i<n;i++)
    44         {
    45             if(!((state>>i)&1))
    46             {
    47                 dp[state]+=dp[state|(1<<i)]*p[i];
    48                 tot+=p[i];
    49             }
    50         }
    51         dp[state]=(dp[state]+1.0)/tot;
    52     }
    53 }
    54 
    55 void print()
    56 {
    57     printf("%.9f
    ",dp[0]);
    58 }
    59 
    60 int main()
    61 {
    62     while(cin>>n)
    63     {
    64         read();
    65         solve();
    66         print();
    67     }
    68 }
  • 相关阅读:
    Centos 6下使用cmake编译安装MariaDB
    mysql索引
    mysql基础指令知识
    git/github安装与使用教程
    Linux目录结构详解
    static关键字的作用(修饰类、方法、变量、静态块)
    Java中重载(overloading)和重写(Overriding)的区别
    @PropertySources和@ImportReSources注解
    @ConfigurationProperties注解和@Value注解的区别
    Java中数组的定义,初始化和使用
  • 原文地址:https://www.cnblogs.com/Leohh/p/7578131.html
Copyright © 2020-2023  润新知