DP嘛,,多刷刷是很有必要的。
题意&算法 都在注释里:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>`
#include <algorithm>
#include <cctype>
#include <set>
#include <string>
#include <vector>
#define INF 0x7fffffff
#define eps (1e-9)
#define clearto(s,x) memset(s,x,sizeof(s))
#define prime 999983
#define maxn 100010
using namespace std;
typedef long long llong;
int n,m,t,tot=0;
double dp[1001][31][31]; // dp[i][j][k]表示第i个队伍对于前j题而言做对k道的概率。
double p[1001][31]; // p[i][j]为第i队通过第j题的概率
int main()
{
//freopen("D:\data.txt","r",stdin);
int TT,i,j,k;
while(~scanf("%d %d %d",&m,&t,&n)) //m道题,t个队,冠军队至少n道
{
if( !m && !t && !n ) break;
clearto(p,0); clearto(dp,0);
for(i=0;i< t;i++)
{
dp[i][0][0]=1;
for(j=1;j<=m;j++) {
scanf("%lf",&p[i][j]);
dp[i][j][0]= dp[i][j-1][0]*(1-p[i][j]);
for(k=1;k<=j;k++)
dp[i][j][k]= dp[i][j-1][k-1]*p[i][j]+dp[i][j-1][k]*(1-p[i][j]);
}
}
double ans =1, tmp =1; //ans每个队至少做一题概率
for(i=0;i< t;i++){
ans*=(1-dp[i][m][0]);
double sum =0; //第i个队在n道题中做1~(n-1)题概率和
for(j=1;j< n;j++) sum +=dp[i][m][j];
tmp *=sum;
}
printf("%.3f\n",ans-tmp); //ans减去 所有队只做1~(n-1)题概率(tmp)
}
return 0;
}