题意:在acm比赛中,n题,t队。给出每个队做对每题的概率,问每队至少对一题,至少有一队做对至少m题的概率。(本解题报告中的n,m与原题中相反)
分析:dp,f[i][j]表示第i个队伍做对第j题的概率。g[i][j][k]表示第i个队伍对于前j题而言做对k道的概率。
g[i][j][k] = g[i][j - 1][k - 1] * (f[i][j]) + g[i][j - 1][k] * (1 - f[i][j]);
有了所有的g,我们就可以求出每个队至少做对1题的概率:ans *= 1 - g[i][n][0];
再减去每个队都只做对1~m-1题的概率(把每个队做对1~m-1题的概率加和,并把各队结果相乘)
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 35
#define maxt 1005
int n, t, m;
double f[maxt][maxn];
double g[maxt][maxn][maxn];
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d%d%d", &n, &t, &m), n | t | m)
{
double ans =1;
for (int i =0; i < t; i++)
for (int j =1; j <= n; j++)
scanf("%lf", &f[i][j]);
memset(g, 0, sizeof(g));
for (int i =0; i < t; i++)
{
g[i][0][0] =1;
for (int j =1; j <= n; j++)
{
g[i][j][0] = g[i][j -1][0] * (1- f[i][j]);
for (int k =1; k <= j; k++)
g[i][j][k] = g[i][j -1][k -1] * (f[i][j])
+ g[i][j -1][k] * (1- f[i][j]);
}
}
for (int i =0; i < t; i++)
ans *=1- g[i][n][0];
double temp =1;
for (int i =0; i < t; i++)
{
double sum =0;
for (int j =1; j < m; j++)
sum += g[i][n][j];
temp *= sum;
}
ans -= temp;
printf("%.3f\n", ans);
}
return0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 35
#define maxt 1005
int n, t, m;
double f[maxt][maxn];
double g[maxt][maxn][maxn];
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d%d%d", &n, &t, &m), n | t | m)
{
double ans =1;
for (int i =0; i < t; i++)
for (int j =1; j <= n; j++)
scanf("%lf", &f[i][j]);
memset(g, 0, sizeof(g));
for (int i =0; i < t; i++)
{
g[i][0][0] =1;
for (int j =1; j <= n; j++)
{
g[i][j][0] = g[i][j -1][0] * (1- f[i][j]);
for (int k =1; k <= j; k++)
g[i][j][k] = g[i][j -1][k -1] * (f[i][j])
+ g[i][j -1][k] * (1- f[i][j]);
}
}
for (int i =0; i < t; i++)
ans *=1- g[i][n][0];
double temp =1;
for (int i =0; i < t; i++)
{
double sum =0;
for (int j =1; j < m; j++)
sum += g[i][n][j];
temp *= sum;
}
ans -= temp;
printf("%.3f\n", ans);
}
return0;
}