题意:有 M 个问题,T 只队伍, 给定 p[ i ][ j ] 表示第 i 只队伍解决第 j 个问题的概率, 求所有队伍解决至少一个问题并且冠军(解决问题最多的队伍)解题数 >= N 的概率
分析:设 dp[ i ][ j ][ k ] 表示 第 i 只队伍在前 j 个问题里解决 k 个问题的概率,
比较容易可以推出转移方程 dp[ i ][ j ][ k ] = dp[ i ][ j-1 ][ k-1 ] * p[ i ][ j ] + dp[ i ][ j-1 ][ k ] * (1 - p[ i ][ j ])
由题意 设 p1 为所有队伍解决至少一个问题的概率, p2 为所有队伍解决问题数皆处于 [ 1 , n-1 ] 的概率,
则题解为 p1 - p2 。
p1 =
p2 =
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int M = 35;
double dp[M][M],p[M];
int m,tt,n;
int main()
{
while(cin>>m>>tt>>n&&(m||tt||n))
{
double p1=1.0 , p2=1.0;
for(int t=1;t<=tt;t++) //滚动数组节省空间
{
memset(dp,0,sizeof(dp));
dp[0][0]=1.0;
for(int i=1;i<=m;i++)
{
cin>>p[i];
for(int j=0;j<=i;j++)
{
if(j==0) dp[i][j]=dp[i-1][0]*(1-p[i]);
else dp[i][j]=dp[i-1][j-1]*p[i]+dp[i-1][j]*(1-p[i]);
}
}
p1*=(1-dp[m][0]);
double sum=0.0;
for(int i=1;i<n;i++)
{
sum+=dp[m][i];
}
p2*=sum;
}
printf("%.3f\n",p1-p2);
}
return 0;
}