这道题的大概意思就是说有n支队伍,t道题,并且给你每支队伍答对每道题的概率,然后问你的就是使所有队伍都过至少一道题,并且第一名的队伍答对至少m道题的概率是多少。
我们先看下如何解决一个队伍的情况,比如说,有t道题,那么我们如何求答对k(t>=k>=0)道题的概率呢?我们考虑使用dp进行递推!定义dp[i][j]表示前i道题中答对j道题的概率,这个时候我们就可以很简单的写出状态转移方程如下:dp[i][j]=dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i],其中p[i]表示答对第i道题的概率,得到状态转移方程之后就好写了。
那么对于题目中的问题如何解答呢?题目中问的是要使每一支队伍答对的题数大于等于1,并且冠军的题数一定要大于等于m,我们可以求出所有球队过题数大于等于1的概率,然后减去所有队伍过题数都收介于1和m-1之间的概率就是题目中要求的概率。知道这些,这道题就好做了。
附上我的代码给参考下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int Max=1002;
double dp[Max][32][32];
double p[Max][32];
int main()
{
int n,m,t;
while(scanf("%d %d %d",&t,&n,&m))
{
if(n==0&&t==0&&m==0)
break;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=t;j++)
scanf("%lf",&p[i][j]);
}
for(int k=1;k<=n;k++)
{
dp[k][0][0]=1.0;
for(int i=1;i<=t;i++)
{
for(int j=i+1;j<=t;j++)
{
dp[k][i][j]=0.0;
}
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=t;i++)
{
for(int j=0;j<=i;j++)
{
dp[k][i][j]=dp[k][i-1][j]*(1-p[k][i]);
if(j>0)
dp[k][i][j]+=dp[k][i-1][j-1]*p[k][i];
// printf("%d %d %d %.2lf\n",k,i,j,dp[k][i][j]);
}
}
}
double a=1.0,b=1.0;
for(int k=1;k<=n;k++)
{
a*=(1.0-dp[k][t][0]);
double temp=0.0;
for(int i=1;i<m;i++)
{
temp+=dp[k][t][i];
}
b*=temp;
}
printf("%.3f\n",a-b);
}
return 0;
}