您的位置:首页 > 其它

★HDU 4336 Card Collector 详细题解(状压求期望)

2017-03-25 14:10 288 查看


Card Collector

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4309    Accepted Submission(s): 2172
Special Judge


Problem Description

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.

 

Input

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

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.

 

Sample Input

1
0.1
2
0.1 0.4

 

Sample Output

10.000
10.500

 

Source

2012 Multi-University Training Contest 4

解题思路:状态压缩求概率。

 dp[(1<<n)-1]=0,dp[i]=(sum(dp[i|(1<<j)]*a[j])+1)/(sum(a[j]));j为所有j&(1<<i)==0,dp[0]即为所求

1、期望公式:E=sum(xi*pi)。等于某一件事件的状态*它发生的概率。

在高中课本里就是列个分布列然后求期望。

我们用二进制枚举卡片表示各个状态。1表示已经集齐,0表示还没有。

从末态倒推到起始状态。

这里我们看每个状态是可能由哪个状态转移而来,乘以这个转移事件发生的概率

就是当前状态得到的期望了。

要注意的是这个转移事件发生的概率的理解:
它不是输入的那个概率,而是当前可以发生的转移中正在计算的转移所占的概率。

即如果当前状态能够从n种状态转移得来,则第i种发生的概率为pi/sum(p1....pn) ,其中sum(p1...pn)

p1...pn只是m个事件的子集(可以等于)

简而言之:

期望可以分解成多个子期望的加权和,权为子期望发生的概率,即 E(aA+bB+...) = aE(A) + bE(B) +...

权为子期望发生的概率,题目中的哪个概率并不是这个状态发生的概率,应该是pi/sum(p1....pn);
这就是为什么要除以能发生转移的概率和的原因。也是我高中学期望的时候老是出错的地方。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 20;
double dp[1<<maxn], p[maxn];
int main()
{
int n;
while(~scanf("%d", &n))
{
double cur = 0;
for(int i = 0; i < n; i++)
{
scanf("%lf", &p[i]);
cur += p[i];
}
memset(dp, 0, sizeof(dp));
int last = (1 << n)-1;
for(int i = last-1; i >= 0; i--) //状压枚举所有可能性
{
double temp = 1-cur;
for(int j = 0; j < n; j++)
{
if((1<<j)&i) temp += p[j];
else dp[i] += dp[i|(1 << j)]*p[j]; //这里的每一个p[j]都应该除以所有没有抽到的总概率,因为p[j]只是这个包抽到卡的概率,并不是抽到卡这件事发生的概率,求期望应该是子期望发生的概率
}
dp[i] = (dp[i]+1.0)/(1-temp);
// dp[i] = sum/(1-temp);
}
printf("%.5f\n", dp[0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: