UVA 11181 Probability|Given dfs模拟组合情况(周赛F题)

条件模拟,这题纠结了好久,题目本身就看了好久才理解题意……

题目大意:有n个人去超市买东西,给出r,每个人买东西的概率是p[i],求:当有r个人买东西的时候,第i个人恰好买东西的概率。

例如:

3 2
0.10
0.20
0.30
有两个人是一定买东西的,但是不知道是哪两个。所以情况有:
(1)第一个人和第二个人买,第三个人不买(即(1,1,0)),则概率:0.10*0.20*(1-0.30)=0.014;
(2)第一个人和第三个人买,第二个人不买(即(1,0,1)),则概率:0.10*(1-0.20)*0.30=0.024
(3)个人和第三个人买,第一个人不买(即(0,1,1)),则概率:(1-0.10)*0.20*0.30=0.054。  
则这三个人买的总概率为:0.014+0.024+0.054=0.092;
第一个人买的概率为:0.014+0.024=0.038;
第二个人买的概率为:0.014+0.054=0.068;
第三个人买的概率为:0.024+0.054=0.078。
则第一个人买的条件概率为:0.038/0.092=0.413043;
则第一个人买的条件概率为:0.068/0.092=0.739130;
则第一个人买的条件概率为:0.078/0.092=0.847826;
dfs可以模拟组合的情况:代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
double p[23],pi[23],sum;
int n,r,vis[23];
void dfs(int st, int t)
{
    int i;
    double pn;
    if(t==r)
    {
        pn=1.0;
        for(i=1; i<=n; i++)
        {
            if(vis[i]) pn*=p[i];
            else pn*=(1-p[i]);
        }
        for(i=1; i<=n; i++)
            if(vis[i]) pi[i]+=pn;
        sum+=pn;
        return ;
    }
    for(i=st; i<=n; i++)
    {
        vis[i]=1;
        dfs(i+1,t+1);
        vis[i]=0;
    }
}
int main()
{
    int i,k=1;
    while(scanf("%d%d",&n,&r)&&(n||r))
    {
        for(i=1; i<=n; i++)
            scanf("%lf",&p[i]);
        mem(pi,0);
        mem(vis,0);
        sum=0;
        dfs(1,0);
        printf("Case %d:\n",k++);
        for(i=1; i<=n; i++)
            printf("%.6f\n",pi[i]/sum);
    }
    return 0;
}


你可能感兴趣的:(UVA 11181 Probability|Given dfs模拟组合情况(周赛F题))