uva 11181 : Probability | Given (条件概率)

题面大意:有n个人去超市,第i个人有pi的概率买东西。逛完以后你得知有r个人买了东西。根据这一信息,请计算每个人实际买了东西的概率。输入n (1 <= n <= 20) 和 r (0 <= r <= n),输出每个人实际买了东西的概率。

解法:条件概率,设第i个人买了东西为事件Ai,r个人买了东西为事件B,要求的是P(Ai | B) = P(Ai B) / P(B) (条件概率公式),注意这是离散型但不是古典型,不能直接用样本点数除以样本空间,因为基本事件概率不相同。要运用全概率公式,假设有4个人,其中2个人买了东西,所有的情况是1100,1010,1001,0110,0101,0011(1表示买了东西,0表示没买东西)。这些事件为B事件的所有情况,1100的概率就是 : p1 * p2 * ( 1 - p3) * (1 - p4),P(B)就是这些概率的总和,设为tot。第i个人有买东西的概率是所有第i位为1的概率的总和,设为sumi。
答案就是sumi / tot。

具体实现:可以用dfs枚举r元子集。

#include<bits/stdc++.h>
using namespace std;
int n,r;
const int maxn = 1e3 + 10;
double p[maxn];
double ans[maxn];
int vis[maxn];
double res;
void dfs(int cur,int num,double &res) {
    if(cur > n) {
    	if(num == 0) {
        	double tmp = 1;
        	for(int i = 1; i <= n; i++) {
        	    if(vis[i]) tmp *= p[i];
        	    else tmp *= (1 - p[i]); 
        	}
        	for(int i = 1; i <= n; i++) {
        	    if(vis[i]) ans[i] += tmp;
        	}
        	res += tmp;
        }
        return ;
    }
    if(num > 0) {
 	    vis[cur] = 1;
    	dfs(cur + 1,num - 1,res);
    	vis[cur] = 0;
	}
    dfs(cur + 1,num,res);
}
int main() {
	int ca = 0;
    while(scanf("%d%d",&n,&r) && n && r) {
        res = 0;
        for(int i = 1; i <= n; i++) ans[i] = 0;
        for(int i = 1; i <= n; i++)
            scanf("%lf",&p[i]);
        dfs(1,r,res);
        printf("Case %d:\n",++ca);
		for(int i = 1; i <= n; i++) {
            printf("%lf\n",ans[i] / res);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41997978/article/details/89785026
今日推荐