题意:略;
分析:见code
个人想法: 面对%.3lf而WA无数次的我我,只想说:"我有一句***不知当讲不当讲..."
/**
* 概率dp
* c个问题,n支队伍, 冠军要求解题数m
* 求所有队伍至少解出一题以及至少有一支队伍(冠军)做出M道题的概率P
* 设 概率A: 所有队伍都至少解出一题
* 概率B: 所有队伍都至少解出一题但至多解出M-1题
* 则可知:
* P = A-B
* 求A: 每个队伍至少做出一题的概率的乘积
* 求B:利用dp思想;
* 所有队伍都至少解出一题但至多解出M-1题
* 转化成, 解出1题,解出2题,解出3题......解出M-1题;
* 设ans[i][j][k]: i表示第i支队伍, j表示第i支队伍做前j题, k表示前j题做出了k道题
* 则推出方程为:
* ans[i][j][k] = ans[i][j-1][k]*(1-p[i][j]) + ans[i][j-1][k-1]*p[i][j];
* 即
* 前j-1道题已经做出了k道题, 则第j道题不必做出即可满足前j道题做出k道题
* +
* 前j道题已经做出了k-1道题, 则第j道题须做出来才能满足前j道题做出k道题
* 则 B = (ans[i][c][1~M-1])累加和 (i = 1, 2, 3, 4, ... n);
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int n, m, c;
double ans[maxn][40][40];
double p[maxn][40];
void solve(){
int i=1, j, k;
for(i=1; i<=n; i++){ //第i支队伍
ans[i][0][0] = 1.0;
for(j=1; j<=c; j++) ans[i][j][0] = ans[i][j-1][0]*(1-p[i][j]);
for(j=1; j<=c; j++){//前j题
for(k=1; k<=j; k++){
ans[i][j][k] = ans[i][j-1][k]*(1-p[i][j]) + ans[i][j-1][k-1]*p[i][j];
// cout << ans[i][j][k]<<endl;
}
}
// cout <<"***********\n";
}
return ;
}
int main(){
//freopen("in.txt", "r",stdin);
int i, j, k;
/*c个问题,n支队伍, 冠军要求解题数m*/
while(~scanf("%d %d %d", &c, &n, &m), c||n||m){
double A=1.0, B=1.0, tmp=1.0;
memset(ans, 0, sizeof(ans));
memset(p, 0, sizeof(p));
for(i=1; i<=n; i++){
for(j=1; j<=c; j++){
scanf("%lf", &p[i][j]);
}
}
solve();
for(i=1; i<=n; i++){
A*=(1-ans[i][c][0]);//每只队伍至少做出一题的概率
tmp = 0;
for(k=1; k<=m-1; k++){
tmp += ans[i][c][k];
}
B *= tmp;
// cout <<"*********\n";
}
// cout <<"*********\n";
printf("%.3f\n", A-B);//POJ上%.3lf会WA...
}
return 0;
}