题意:M道题,T个队伍,冠军至少要写N道题。然后给出一个T*M的矩阵,第i,j位置表示第i个队写出第j道题的概率,问所有队都写出来题且冠军至少写出N题的概率?
思路:先考虑这个概率该怎么求。所有队都写出来题且冠军至少写出N题的概率 =
所有队都写出来题的概率 - 所有队都写出来1~N-1道题
所有队都写出来题的概率 = (1 - 第1队写不出题的概率)*(1 - 第2队写不出题的概率)... *(1 - 第T队写不出题的概率)
所有队都写出来1~N-1道题 = (第1队写出来1~N-1题的概率)*(第2队写出来1~N-1题的概率)... *(第T队写出来1~N-1题的概率)
第i队写出来(1~N-1题的概率)= (第i队写出1题的概率)+(第i队写出2题的概率)... +(第i队写出N-1题的概率)
我们要求出每个队写出来0~M道题的概率,但是这样不太好推DP方程,所以我们多加一维。
dp[i][j][k]表示第i个队写出前j道题目中k道的概率。
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1005;
int M, T, N;
double p[1005][35], dp[1005][35][35];//第i个队写出前j道题目中k道的概率
int main()
{
while (~scanf("%d%d%d", &M, &T, &N) && (M+T+N))
{
for (int i = 1; i <= T; i++)
{
for (int j = 1; j <= M; j++)
{
scanf("%lf", &p[i][j]);
}
}
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= T; i++) dp[i][0][0] = 1;
for (int i = 1; i <= T; i++)//第i队
{
for (int j = 1; j <= M; j++)//前j道题
{
for (int k = 0; k <= j; k++)//写出k道
{
dp[i][j][k] = dp[i][j][k] + dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1.0-p[i][j]);
}
}
}
double p1 = 1.0, p2 = 1.0;
for (int i = 1; i <= T; i++)//每个队都写出至少一题的概率
p1 = p1 * (1.0 - dp[i][M][0]);
for (int i = 1; i <= T; i++)
{
double sum = 0.0;//第i队写出1~N-1题的概率
for (int k = 1; k < N; k++)
{
sum = sum + dp[i][M][k];
}
p2 *= sum;//所有队都写出了1~N-1题的概率
}
printf("%.3f\n", p1 - p2);
}
return 0;
}
/*
2 2 2
0.9 0.9
1 0.9
0 0 0
*/