Probability|Given UVA - 11181

题意:有n个人准备去超市逛,其中第i个人买东西的频率是Pi。逛完以后得知有r个人买了东西,计算每个人实际买了东西的频率。输入n(1<=n<=20)和r(0<=r<=n),输出每个人实际买了东西的频率。

思路:“r个人买了东西”这个事件叫做E,“第i个人买东西”这个事件为Ei,要求P(Ei|E) = P(EiE) / P(E).条件概率公式

1.计算P(E).递归方式计算所有可能r个人买了东西的情况,比如n = 4,r = 2,有6种可能1100,1010,1001,0110,0101,0011,其中1100概率为P1 * P2 * (1 - P3) * (1 - P4),设置A[k]表示第k个人是否买东西(0表示没买,1表示买了),可以用递归的方法枚举恰好有r个A[k] = 1的情况

2.计算P(EiE),可以利用第一条时的递归,只不过要保证A[i] = 1

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
const int maxn = 20 + 2;
int n,r,A[maxn];
double tot,p[maxn],ans[maxn];
void dfs(int x,int sum)
{
    if(sum == r)
    {
        double q = 1.0;
        for(int i = 1;i <= n;i++)
        {
            if(A[i]) q *= p[i];
            else q *= (1 - p[i]);
        }
        for(int i = 1;i <= n;i++) if(A[i]) ans[i] += q;
        tot += q;
        return;
    }
    for(int i = x;i <= n;i++)
    {
//        if(A[i]) continue;
        A[i] = 1;
        dfs(i + 1,sum + 1);
        A[i] = 0;
    }
}
int main()
{
    int kase = 1;
    while(scanf("%d%d",&n,&r) && n + r)
    {
        tot = 0;
        memset(A,0,sizeof(A));
        memset(ans,0,sizeof(ans));
        for(int i = 1;i <= n;i++) scanf("%lf",&p[i]);
        dfs(1,0);
        printf("Case %d:\n",kase++);
        for(int i = 1;i <= n;i++)
        {
            printf("%.6f\n",ans[i] / tot);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sgsyacm/article/details/87092812
今日推荐