条件模拟,这题纠结了好久,题目本身就看了好久才理解题意……
题目大意:有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; }