您的位置:首页 > 其它

HDU 4336 概率DP求期望(or容斥原理)

2013-08-11 16:52 363 查看
题意:
有N(1<=N<=20)张卡片,每包中含有这些卡片的概率为p1,p2,````pN.
每包至多一张卡片,可能没有卡片。
求需要买多少包才能拿到所以的N张卡片,求次数的期望。
 
可以用状态压缩dp来求概率,做过基本的概率dp后应该没什么问题
这里我主要说说容斥原理的解法。
如果一个事件发生的概率为p, 那么它第一次发生时的次数期望就是1/p
1:1/p
2:    (1-p)*p
3:    (1-p)^2*p
......
n:    (1-p)^(n-1)*p
以上求和,用错位相消的方法求出 E = 1/p
类似的,我们可以得出 如果两个事件发生的概率分别为p1,p2, 那么
第一次发生其中的某一件的次数期望就是1/(p1+p2)。
根据这个结论我们就可以用容斥原理来做这题了。
容斥:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int n, two[22];double p[22], ans;int main() {int i, j;two[0] = 1;for(i = 1; i <= 20; i++)two[i] = two[i-1] << 1;while( ~scanf("%d", &n)) {for(i = 0; i < n; i++)scanf("%lf", &p[i]);ans = 0;for(i = 1; i < two; i++) {double sum = 0;int c = 0;for(j = 0; j < n; j++)if(i&two[j]) {sum += p[j];c++;}if(c&1) ans +=  1/sum;else ans -= 1/sum;}printf("%f\n", ans);}return 0;}
状态压缩:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;double p[22], dp[1<<20], p0;int two[22];int n;double tp, ans;int main() {int i, j;two[0] = 1;for(i = 1; i <= 20; i++)two[i] = two[i-1] << 1;while( ~scanf("%d", &n) ) {p0 =  0;for(i = 0; i < n; i++) {scanf("%lf", &p[i]);p0 += p[i];}p0 = 1-p0;dp[two-1] = 0;for(i = two-2; i >= 0; i--) {tp = p0; ans = 1;for(j = 0; j < n; j++)if(two[j]&i) tp += p[j];else ans += p[j]*dp[two[j]|i];dp[i] = ans/(1-tp);}printf("%.5f\n", dp[0]);}return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: