题意:给定t个队伍、m场比赛,每个队伍做对每个题的概率,问每个队都至少做对一个题并且第一名做对的题目至少有n道的概率
思路:每个队至少做对1道题的概率很容易求,这个概率记作p,即每个队能做出题的概率的乘积,假设计算第i个队能做出题的概率,也就是1减去这个队做不出题的概率
设p2为每个队都做出1到n-1道题的概率,那么p-p2就是最后的答案了
那么关键就是怎么算p2
我们设dp[i][j][k]为第i个队做前j个题做对k个题的概率,那么
dp[i][j][k]=dp[i][j-1][k]*(1-data[i][j])+dp[i][j-1][k-1]*data[i][j]
代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
double data[1005][35];
double d[35];
double dp[1005][35][35];
double s[1005][35];
int main()
{
int m,t,n;
while(scanf("%d%d%d",&m,&t,&n)!=-1)
{
memset(dp,0,sizeof(dp));
if(m==0&&t==0&&n==0) break;
for(int i=1;i<=t;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%lf",&data[i][j]);
}
}
double p=1;
for(int i=1;i<=t;i++)
{
double p1=1;
for(int j=1;j<=m;j++)
{
p1*=(1-data[i][j]);
}
p*=(1-p1);
}
for(int i=1;i<=t;i++)
dp[i][0][0]=1;
for(int i=1;i<=t;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=0;k<=j;k++)
{
dp[i][j][k]=dp[i][j-1][k]*(1-data[i][j]);
if(k>0)
dp[i][j][k]+=dp[i][j-1][k-1]*data[i][j];
}
}
}
double p2=1;
for(int i=1;i<=t;i++)
{
double p3=0;
for(int j=1;j<=n-1;j++)
{
p3+=dp[i][m][j];
}
p2*=p3;
}
printf("%.3f\n",p-p2);
}
}