题意

你在打比赛,这场比赛总共有12个题

对于第i个题,你的队伍有a[i]的几率解决她

如果解决不了她呢?

由于所有人讨论的都很大声

所以你有b[i]的概率从左边那个队那里听会这个题的做法

有c[i]的概率从右边那个队那里听会这个题的做法

请问最终你们队伍解出0-12题的概率分别是多少

输入描述

第一行12个数表示a[1] -> a[12]
第二行12个数表示b[1] -> b[12]
第三行12个数表示c[1] -> c[12]

输出描述

输出13行,第i行表示解出i-1题的概率
保留6位小数

解析

简答来说就是有三种渠道获得答案,自己做,抄左边的抄右边的,然后这三个都有一个成功的概率,首先我们就应该把做出每一道题的概率给算出来,如果直接对着莽的话有好几种情况,自己做出来的同时抄到了左边的和右边的,或者自己没做出来但是抄到了左边的或者右边的,这样有很多种情况,这样就要讨论很多种情况,我们不妨反过来做,把1减去没做出来的概率就是做出来的概率,这么来看就简单了没做出来的概率就是自己既没做出来,有没有抄到左边的或者右边的,我们把做出来第i题的概率设为d[i]

那么就有:


现在我们解决了第一步,我们来考虑下一步,如何实现。
对!!又是暴力,我又想上图了
图片说明



但是!!!!!!这个题目明显不适合暴力

因为这个题目如果暴力要枚举的情况太多了,不仅时间复杂度高,而且代码量也不小,所以我们要考虑其他的方法,首先我们来分析,答对0道题的概率就是所有题目都答错,然后累乘起来,

好,我们得到了答对0题的概率,然后我们来看一题,这一题我们可以是12道题中的任意一题,这么看就是在答对0题的基础上,选择一道题答对,这么看我们应该想到dp,我们设dp[i][j]表示前i个问题中,对了j个问题的概率

需要特判一下j=0的情况

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
double a[15],b[15],c[15],d[15];
double dp[15][15]={0};
int main(void){
    for(int i=1;i<=12;++i)cin>>a[i];
    for(int i=1;i<=12;++i)cin>>b[i];
    for(int i=1;i<=12;++i)cin>>c[i];
    for(int i=1;i<=12;++i)d[i]=1-(1-a[i])*(1-b[i])*(1-c[i]);
    dp[0][0]=1;
    for(int i=1;i<=12;++i){
        dp[i][0]=dp[i-1][0]*(1-d[i]);
        for(int j=1;j<=i;++j){
            dp[i][j]=dp[i-1][j]*(1-d[i])+dp[i-1][j-1]*d[i];
        }
    }
    for(int i=0;i<=12;++i)
        printf("%.6f\n",dp[12][i]);
    return 0;
}