题目链接: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