紫书P327
题意:有n个人准备去超市逛,其中第i个人买东西的概率是 Pi 。逛完以后你得知有 r 个人买了东西。根据这一信息,计算每个人实际买东西的概率。输入 n ( 1 <= n <= 20 )和r( 0 <= r <= n) 输出每个人实际买了的东西概率
分析: “ r 个人买了东西 ” 这个事件叫做E, “ 第 i 个人买东西 ”这个事件叫做 Ei ,要求的就是 P( Ei | E ) = P ( Ei E) / P ( E ) ;
P(E)的求法利用全概率公式,每一种可能的情况的概率相加,假设 n = 4, r = 2, 有6中可能:1100,1010,1001,0110,0101,0011,其中1100的概率就是P1 * P2 * ( 1 - P3) * ( 1 - P4), 其他的类似,假设求 P ( E1 E ) 就等于所有 P1 被访问过的,即等于1的每种可能之和,sum[ i ] 表示 vis[ i ] = 1 的概率之和,tot表示总概率和
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int Max = 30; 7 double p[Max],sum[Max],tot; 8 int n,r; 9 int vis[Max],A[Max]; 10 void dfs(int cur, int cnt) 11 { 12 if(cnt == r) 13 { 14 double ans = 1; 15 for(int i = 1; i <= n; i++) 16 { 17 if(vis[i]) 18 { 19 ans *= p[i]; 20 } 21 else 22 { 23 ans *= (1 - p[i]); 24 } 25 } 26 for(int i = 1; i <= n; i++) 27 { 28 if(vis[i]) 29 { 30 sum[i] += ans; 31 } 32 } 33 tot += ans; 34 } 35 for(int i = cur + 1; i <= n; i++) 36 { 37 if(vis[i] == 0) 38 { 39 vis[i] = 1; 40 A[cnt + 1] = i; 41 dfs(i, cnt + 1); 42 vis[i] = 0; 43 } 44 } 45 } 46 int main() 47 { 48 int test = 0; 49 while(scanf("%d%d", &n, &r) != EOF) 50 { 51 if(n == 0 && r == 0) 52 break; 53 for(int i = 1; i <= n; i++) 54 { 55 scanf("%lf", &p[i]); 56 } 57 memset(vis, 0, sizeof(vis)); 58 memset(sum, 0, sizeof(sum)); 59 tot = 0; 60 dfs(0,0); 61 printf("Case %d: ", ++test); 62 for(int i = 1; i <= n; i++) 63 { 64 printf("%.6lf ", sum[i] / tot); 65 } 66 } 67 return 0; 68 }