【每日一题】5月19日比赛
比赛
https://ac.nowcoder.com/acm/problem/14734
题意
你在打比赛,这场比赛总共有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; }
每日一题 文章被收录于专栏
写每日一题呀