/*
概率DP 状压DP 条件期望DP 好题
题意:有n种卡片,一袋面里有一张卡片或者没有。给出每种卡片出现在一袋面里的概率,问要收集完n种卡片所需要买的袋面数目的期望(n <= 20).
思路:状压表当前已收集到的卡片的状态,位为1表收集到了,0表没有收集到。
对于状态T,考虑最近买的那袋面之前的状态S(也就是状态X在买了这袋面之后变成了状态T),
<1>这袋面没有卡片
<2>这袋面的卡片X已经收集过了
<3>这袋面的卡片X还没有收集过
方法1:
前两种情况新旧状态不变,即T = S;后面一种情况S = T ^ (1<<k)
则T数学期望E(T) = 1 + (1 - Σp[i])*E(T) + Σ(p[j]*E(T)) + Σ(p[k]*E(S))
其中:i = 0, 1, 2,...n-1
j = 第j种卡片已经收集过了,S & (1<<j) == 1
k = 第k种卡片还没有收集过,S & (1<<j) == 0
移项可得:E(T) * Σp[k] = 1 + Σ(p[k] * E(S) ,这里的k=第k种卡片没收集到,S = T ^ (1<<k)
ps:我之前一直很奇怪为什么大家的代码没有对“袋面里可能没有卡片”这一点做处理,后来实在上面的移项过程种想明白的,移项的时候可以把情况<1>和<2>归到一起。我才想明白,其实袋子是否有可能为空并不影响做题,我们可以把空袋子当作一张“隐形卡”,每个状态都默认已经有了这张卡,所以情况<1>可以直接归为情况2,因为不存在空的情况了,隐形卡大家已经收集过了。
===================================================================================================================
方法2:
其实上述式子可以由条件期望的原理很容易地得出...
首先 E(X|Y=y) = Σxf(x|y)
E(E(X|Y)) = EX, 我们叫EX为全体加权平均,E(X|Y)为条件加权平均(局部加权平均),在这道题里X != Y
这样,我们就可以直接得出上述的公式了:
E(X|Y)/Σpy = EX
Σ(E(Y)*py) / Σpy = EX
其实条件期望我也是晕晕忽忽的,详细看:http://blog.csdn.net/henhen2002/article/details/5540039
*/
概率DP 状压DP 条件期望DP 好题
题意:有n种卡片,一袋面里有一张卡片或者没有。给出每种卡片出现在一袋面里的概率,问要收集完n种卡片所需要买的袋面数目的期望(n <= 20).
思路:状压表当前已收集到的卡片的状态,位为1表收集到了,0表没有收集到。
对于状态T,考虑最近买的那袋面之前的状态S(也就是状态X在买了这袋面之后变成了状态T),
<1>这袋面没有卡片
<2>这袋面的卡片X已经收集过了
<3>这袋面的卡片X还没有收集过
方法1:
前两种情况新旧状态不变,即T = S;后面一种情况S = T ^ (1<<k)
则T数学期望E(T) = 1 + (1 - Σp[i])*E(T) + Σ(p[j]*E(T)) + Σ(p[k]*E(S))
其中:i = 0, 1, 2,...n-1
j = 第j种卡片已经收集过了,S & (1<<j) == 1
k = 第k种卡片还没有收集过,S & (1<<j) == 0
移项可得:E(T) * Σp[k] = 1 + Σ(p[k] * E(S) ,这里的k=第k种卡片没收集到,S = T ^ (1<<k)
ps:我之前一直很奇怪为什么大家的代码没有对“袋面里可能没有卡片”这一点做处理,后来实在上面的移项过程种想明白的,移项的时候可以把情况<1>和<2>归到一起。我才想明白,其实袋子是否有可能为空并不影响做题,我们可以把空袋子当作一张“隐形卡”,每个状态都默认已经有了这张卡,所以情况<1>可以直接归为情况2,因为不存在空的情况了,隐形卡大家已经收集过了。
===================================================================================================================
方法2:
其实上述式子可以由条件期望的原理很容易地得出...
首先 E(X|Y=y) = Σxf(x|y)
E(E(X|Y)) = EX, 我们叫EX为全体加权平均,E(X|Y)为条件加权平均(局部加权平均),在这道题里X != Y
这样,我们就可以直接得出上述的公式了:
E(X|Y)/Σpy = EX
Σ(E(Y)*py) / Σpy = EX
其实条件期望我也是晕晕忽忽的,详细看:http://blog.csdn.net/henhen2002/article/details/5540039
*/
#include <stdio.h>
#define MAXN 25
double p[MAXN], f[1 << MAXN];
int n;
int main()
{
while(scanf("%d", &n) != EOF) {
for(int i = 0; i < n; i++) scanf("%lf", &p[i]);
f[0] = 0;
int top = (1 << n);
for(int u = 1; u < top; u++) {
double sum = 0, tmp = 0;
sum += 1;
for(int i = 0; i < n; i++) if(u & (1 << i)) {
sum += f[u ^ (1 << i)] * p[i];
tmp += p[i];
}
f[u] = sum/tmp;
}
printf("%f\n", f[top-1]);
}
return 0;
}