P8804题解

· · 题解

前置知识:

这一题要用到贝叶斯公式,接下来我们看一下贝叶斯公式:就是 P(B|A)=\frac{P(A|B)×P(B)}{P(A)} ,这里 A 事件发生的概率为 P(A)B 事件发生的概率为 P(B)A 事件发生时 B 事件发生的概率为 P(B|A)

题目大意

其实题目那么长,其实就是要判断每种故障的出现概率,最后 sort 快排一下输出即可。

题目解答

这题在计算的时候要用到贝叶斯公式。

首先,定义 a 数组,a[i] 表示故障原因 i 产生的概率 P_{i} ;还有 b 数组(是一个二维数组),b[i][j] 表示故障原因 i 出现故障现象 j 的概率,因为这两个数组都是用百分比输入的,所以先转成小数。

然后,定义一个浮点类型的数 sum 表示当前故障原因发生并且产生出现的现象的概率,和一个数组 dp 计算第 i 故障发生并且导致出现当前现象的概率,最后的 sum 就是把数组 dp 的所有数累加起来。

接着,一个 for 循环,就是如果这个现象发生了,就标记为 1

接下来一个 for 循环,就是用叶贝斯公式计算 dp[i]

最后把故障的编号和发生故障的概率统计一下,输出即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=500;
double a[maxn],b[maxn][maxn],dp[maxn];
int N,M,K,c[maxn];
struct bro{
    int id;double p;
}d[maxn];
bool cmp(bro x,bro y){
    if(fabs(x.p-y.p)<1e-6)return x.id<y.id;//防止精度丢失 
    return x.p>y.p; 
}
int main(){
    cin>>N>>M;
    int i,j,k;
    double sum=0;//当前故障原因发生并且产生出现的现象的概率 
    for(i=1;i<=N;i++){
        cin>>a[i];
        a[i]*=0.01;//百分比还原成小数 
    } 
    for(i=1;i<=N;i++)
        for(j=1;j<=M;j++){
            cin>>b[i][j];
            b[i][j]=b[i][j]*0.01;//百分比还原成小数 
        } 
    cin>>K;
    for(i=1;i<=K;i++){
        cin>>k;
        c[k]=1;//这个现象发生了 
    }
    for(i=1;i<=N;i++){//i故障发生并且导致出现当前现象的概率 
        dp[i]=a[i];
        for(j=1;j<=M;j++){
            if(c[j])dp[i]=dp[i]*b[i][j];
            else dp[i]=dp[i]*(1-b[i][j]);
        } 
    } 
    for(i=1;i<=N;i++)sum+=dp[i];//发生当前现象的总概率 
    for(i=1;i<=N;i++){
        d[i].id=i;//记录故障编号 
        d[i].p=dp[i]*100.0/sum;//计算故障概率 
    }
    sort(d+1,d+N+1,cmp);
    for(i=1;i<=N;i++)printf("%d %.2lf\n",d[i].id,d[i].p); 
    return 0;
}