题目链接:http://poj.org/problem?id=2151
Description
Input
Output
Sample Input
2 2 2 0.9 0.9 1 0.9 0 0 0
Sample Output
0.972
题意:
比赛中,共 m 道题,t 个队,p[i][j]表示第 i 队解出第 j 题的概率
问:每队至少解出一题且冠军队至少解出 n 道题的概率。
PS:p[i][j]表示第i个队伍做对第j题的概率。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]);
再求出每个队都至少做对 1 道题的概率:tt *= 1 - dp[i][m][0];
最后再减去每个队都只做对了 1 ~ n-1 题的概率;
即:(把每个队做对 1 ~ n-1 题的概率相加后,并把每个队的结果相乘);
代码如下:
//PS:p[i][j]表示第i个队伍做对第j题的概率。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]);
//
//再求出每个队都至少做对 1 道题的概率:tt *= 1 - dp[i][m][0];
//
//最后再减去每个队都只做对了 1 ~ n-1 题的概率;
//即:(把每个队做对 1 ~ n-1 题的概率相加后,并把每个队的结果相乘)
#include <cstdio>
#include <cstring>
double p[1017][47];
double dp[1017][47][47];
int main()
{
int n, m, t;
while(~scanf("%d%d%d",&m,&t,&n))
{
if(m==0 && t==0 && n==0)
break;
memset(p, 0,sizeof(p));
memset(dp, 0,sizeof(dp));
for(int i = 0; i < t; i++)
{
for(int j = 1; j <= m; j++)
{
scanf("%lf",&p[i][j]);
}
}
for(int i = 0; i < t; i++)
{
dp[i][0][0] = 1;
for(int j = 1; j <= m; j++)
{
dp[i][j][0] += dp[i][j-1][0] * (1-p[i][j]);
for(int k = 1; k <= j; k++)
{
dp[i][j][k] = dp[i][j-1][k-1]*p[i][j]+dp[i][j-1][k]*(1-p[i][j]);
}
}
}
double tt = 1;
for(int i = 0; i < t; i++)
{
tt*=(1 - dp[i][m][0]);
}
double temp = 1, t_sum;
for(int i = 0; i < t; i++)
{
t_sum = 0;
for(int j = 1; j <= n-1; j++)
{
t_sum+=dp[i][m][j];
}
temp *= t_sum;
}
double ans = tt-temp;
printf("%.3lf\n",ans);
}
return 0;
}
POJ 2151 Check the difficulty of problems(概率dp)
原文地址:http://blog.csdn.net/u012860063/article/details/43564311