题意:m到题T个队伍,给出每一个队伍做出每一道题的概率,询问所有队伍都至少解决一道题目且做的最多的队伍做的题目大于等于n的概率。
感觉还是一道很有趣的dp。首先考虑求至少每一个队伍都至少解决一道题目可以怎么解决?这个很简单,可以先算出每个队一道题都解决不了,然后用1减去就可以了。现在考虑至少有一个队伍要求解决的题目的数目超过n该如何解决,类似于刚才的想法我们社p为所有队伍都解决不了超过等于n道题的概率所以最后的答案就是p1*(1-p)换出来就是p1-p1*p
可以用f[i][j][k]表示第i个人对于钱j道题解决了k道题的概率与处理出每一个人做k道题的概率(即f[i][m][k])方程:
f[i][j][k]=f[i][j-1][k]*(1-p[j])+f[i][j-1][k-1]*p[j]
为了方便令dp[i][j]表示第i个人最多做j道题的概率(用刚才的转移就好了)
最后统计一下答案就好了
#include<cstdio>
#include<cstring>
#include<iostream>
#define clean(a) memset(a,0,sizeof(a))
using namespace std;
int T,m,n;
double f[1002][32][32],dp[1002][32],mat[1002][32];
//f[i][j][k]表示对于第i个队伍 前j个题目解出了k道题目的概率
//dp[i][j] 表示第i个队伍至少做出j道题目的几率
int main(){
while(scanf("%d%d%d",&m,&T,&n)&&(m+T+n)){
clean(f),clean(dp),clean(mat);
for(int i=1;i<=T;i++){
f[i][0][0]=1.0;
for(int j=1;j<=m;j++)
scanf("%lf",&mat[i][j]);
}
for(int i=1;i<=T;i++){
for(int j=1;j<=m;j++){
for(int k=0;k<=j;k++){
f[i][j][k]=f[i][j-1][k]*(1-mat[i][j]);
if(k!=0)f[i][j][k]+=f[i][j-1][k-1]*mat[i][j];
}
}
}
for(int i=1;i<=T;i++){
dp[i][0]=f[i][m][0];
for(int j=1;j<=m;j++)dp[i][j]=f[i][m][j]+dp[i][j-1];
}
double ans1=1,ans2=1;
for(int i=1;i<=T;i++){
ans1*=1-dp[i][0];
ans2*=(dp[i][n-1]-dp[i][0]);
}
printf("%.3lf\n",ans1-ans2);
}
return 0;
}/*
2 2 2
0.9 0.9
1 0.9
0 0 0
*/