题目链接:http://poj.org/problem?id=2151
题意:有m道题,T个队伍,每支队伍对于每个题目都有一个概率将其做出来,求每支队伍至少做出一题且至少有一个队伍做出的题目不小于n道的概率。
思路:首先每支队伍至少做出一题的概率,每个队伍做题目是独立的,所以将每支队伍至少做出一题的概率乘起来得到概率p。在当前情况下,再求至少有一个队伍做出的题目不小于n,那么就用1减去每支队伍的解题量都在1~n-1之间的概率。对于每支队伍f[i][j]表示前i个题目做出来j个的概率,f[i][j] = f[i-1][j-1]*p + f[i-1][j] * (1-p)。gi = ∑f[m][i] i∈[1,n-1]为第i个队伍解出1~n-1道题的概率。答案为p - ( ∏gi )
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007
int m,T,n;
double p[1009][39];
bool init()
{
scanf("%d%d%d",&m,&T,&n);
if ( m + n + T == 0 ) return false;
rep(i,1,T)
rep(j,1,m) scanf("%lf",&p[i][j]);
return true;
}
double cal( int t )
{
double f[50][50];
Clean(f,0);
f[0][0] = 1;
rep(i,1,m) f[i][0] = f[i-1][0] * ( 1 - p[t][i] );
rep(i,1,m)
rep(j,1,min(m,T))
f[i][j] = f[i-1][j] * ( 1 - p[t][i] ) + f[i-1][j-1] * p[t][i];
double ans = 0;
rep(i,1,n-1) ans += f[m][i];
return ans;
}
void solve()
{
double ans = 1;
double q = 1;
rep(i,1,T)
{
double x = 1;
rep(j,1,m) x *= ( 1 - p[i][j] );
ans *= 1 - x;
q *= cal( i );
}
printf("%0.3f\n",ans - q);
}
int main()
{
while( init() )
{
solve();
}
return 0;
}