这道题的大概意思就是说有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; }