51nod 3144 超级购物

原题链接

3144 超级购物

题目大意

n   ( 1 ≤ n ≤ 20 ) n\ (1\le n\le 20) n (1n20) 个人去逛商场,第 i i i 个人在商场买东西的概率为 p i ( 0.1 < p i < 1 ) p_i(0.1< p_i<1) pi(0.1<pi<1)
他们逛完商场后,已知有 r ( 0 ≤ r ≤ n ) r(0\le r\le n) r(0rn) 个人买了东西,对每个人求他买了东西的概率。

解题思路

可以利用贝叶斯公式来分析 P ( A ) , P ( B ) , P ( A ∣ B ) P(A),P(B),P(A|B) P(A),P(B),P(AB) 之间的关系:
P ( A ∣ B ) = P ( A ∩ B ) P ( B ) = P ( A ) × P ( B ∣ A ) P ( B ) P(A|B )=\frac{P(A\cap B)}{P(B)}=\frac{P(A)\times P(B|A)}{P(B)} P(AB)=P(B)P(AB)=P(B)P(A)×P(BA)
如何求出这个公式的值?我们考虑使用类似解决背包问题的方法(可能是动规,也有可能是递推,我不知道
假设 f i , j f_{i,j} fi,j 表示前 i i i 个人中, j j j 个人进行了购物,那么,可以使用如下的方法进行转移:
f i , j = f i − 1 , j × ( 1 − p i ) + f i − 1 , j − 1 × p i f_{i,j}=f_{i-1,j}\times (1-p_i)+f_{i-1,j-1}\times p_i fi,j=fi1,j×(1pi)+fi1,j1×pi
也就表示,前 i i i 个人中 j j j 个人进行购物的概率为:前 i − 1 i-1 i1 个人中 j j j 个人购物的概率乘上第 i i i 个人不购物的概率( 1 − p i 1-p_i 1pi),再加上前 i − 1 i-1 i1 个人中 j − 1 j-1 j1 个人购物的概率乘上第 i i i 个人购物的概率。(特殊情况:当在运算 P ( 第 n 2 个 人 必 须 购 物 ∣ 一 共 有 n 个 人 购 物 ) P(第n_2个人必须购物|一共有n个人购物) P(n2n) 枚举到前 n 2 n_2 n2 个人时,因为最后还需要乘 p n 2 p_{n_2} pn2,所以本来 f i , j = f i − 1 , j × p n 2 f_{i,j}=f_{i-1,j}\times p_{n_2} fi,j=fi1,j×pn2 只需 f i , j = f i − 1 , j f_{i,j}=f_{i-1,j} fi,j=fi1,j 即可,至于为什么不用加 f i − 1 , j − 1 × p i f_{i-1,j-1}\times p_i fi1,j1×pi 是因为这是不购物的概率,而 n 2 n_2 n2 这个人目前的假设是必须购物)

代码实现

#include<bits/stdc++.h>
using namespace std;
int n,r;
double p[100],f[100][100];
double work(int n2)
{//i表示前i个人,j表示有j个人购物 
	f[0][0]=1;//0个人中0个人购物的概率为1
	for(int i=1;i<=n;i++){//枚举前i个人购物
		if(i==n2){//必须购物的第n2个人
			for(int j=0;j<=min(i,r);j++)//特殊情况
				f[i][j]=f[i-1][j];
			continue;
		}
		f[i][0]=f[i-1][0]*(1-p[i]);//若j=0还j-1就会RE
		for(int j=1;j<=min(i,r);j++)//转移方程
			f[i][j]=f[i-1][j]*(1-p[i])+f[i-1][j-1]*p[i]; 
	}
	if(n2==0)//当规定第0个人必须购物时,默认为求事件B的概率(所有人中有r个人购物的概率)
		return f[n][r];
	return f[n][r-1];//由于规定了第n2个人必须购物,只需要求出所有人中r-1个人购物的概率即可
}
int main()
{
	cin>>n>>r;
	for(int i=1;i<=n;i++){
		cin>>p[i];
		p[i]=p[i]/100.0;//给定的概率是按照百分比的形式给出的,所以需要除以100
	}
	double B=work(0);//求出事件B的概率
	for(int i=1;i<=n;i++)//求出第i个人购物的概率
		cout<<work(i)*p[i]/B<<" ";
	return 0;
} 

样例

输入

3 2
10 20 30

输出

0.413043 0.739130 0.847826

注意:要求:用户输出与标准输出的绝对误差不超过1e-3

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值