UVa 11181 - Probability|Given(条件概率)
链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2122
题意:
有n个人准备去超市逛,其中第i个人买东西的概率是Pi。逛完以后你得知有r个人买了东西。
根据这一信息,请计算每个人实际买了东西的概率。
输入n(1≤n≤20)和r(0≤r≤n),输出每个人实际买了东西的概率。
分析:
设“r个人买了东西”这个事件为E,“第i个人买东西”这个事件为Ei,则要求的是条件概率P(Ei|E)。
根据条件概率公式,P(Ei|E) = P(EiE) / P(E)。
P(E)依然可以用全概率公式。例如,n=4,r=2,有6种可能:1100, 1010, 1001, 0110, 0101, 0011,
其中1100的概率为P1*P2*(1-P3)*(1-P4),其他类似,设opt[k]表示第k个人是否买东西(1表示买,0表示不买),
则可以用递归的方法枚举恰好有r个opt[k]=1的情况。
如何计算P(EiE)呢?方法一样,只是枚举的时候要保证第opt[i]=1。
用tot表示E的概率,sum[i]表示opt[i]=1的概率之和,则答案为P(EiE)/P(E)=sum[i]/tot。
代码:
1 import java.io.*; 2 import java.util.*; 3 4 public class Main { 5 static final int UP = 20 + 5; 6 static int n, r; 7 static double P[] = new double[UP], sum[] = new double[UP]; 8 static boolean opt[] = new boolean[UP]; 9 10 static void dfs(int d, int s, double prob) { // d为第几个,s为选了几个,prob为当前概率 11 if(s > r || d - s > n - r) return; // 选的个数超过了限制或者不选的个数超过了限制 12 if(d == n) { 13 sum[n] += prob; 14 for(int i = 0; i < n; i++) if(opt[i]) sum[i] += prob; 15 return; 16 } 17 opt[d] = true; 18 dfs(d+1, s+1, prob * P[d]); 19 opt[d] = false; 20 dfs(d+1, s, prob * (1-P[d])); 21 } 22 23 public static void main(String args[]) { 24 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 25 for(int cases = 1; ; cases++) { 26 n = cin.nextInt(); 27 r = cin.nextInt(); 28 if(n == 0) break; 29 for(int i = 0; i < n; i++) P[i] = cin.nextDouble(); 30 31 Arrays.fill(sum, 0); 32 Arrays.fill(opt, false); 33 dfs(0, 0, 1); 34 35 System.out.printf("Case %d:\n", cases); 36 for(int i = 0; i < n; i++) 37 System.out.printf("%.6f\n", sum[i] / sum[n]); 38 } 39 cin.close(); 40 } 41 }