题目链接:http://poj.org/problem?id=2151
题意:
ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率
问 每队至少解出一题且冠军队至少解出N道题的概率
分析:
对于需要求得概率比较容易想到:
假设p1为每个队至少解出一题的概率,这个容易算出。
假设p2为每个队至少解出一题但是不超过n-1题的概率
所以最终答案为:p1-p2
现在问题是如何求出p2?
假设dp[i][j]表示第i个队解出的题目<=j的概率
则dp[i][j]=解出1题+解出2题+...解出j题的概率
现在问题转化为如何求解出1,2,3...k题的概率
假设x[i][j][k]表示第i个队在前j题解出k题的概率
则:
x[i][j][k]=x[i][j-1][k-1]*p[i][j]+x[i][j-1][k]*(1-p[i][j]);
所以x[i][M][k]表示的就是第i个队解出k题的概率
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cstdlib> 6 #include <cmath> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <vector> 11 #define INF 0x3f3f3f3f 12 using namespace std; 13 14 double an[1010][35], dp[1010][35], sn[1010][35][35]; 15 int main() 16 { 17 int n, t, m; 18 while(~scanf("%d %d %d", &m, &t, &n) && n + t + m) 19 { 20 memset(sn, 0, sizeof(sn)); 21 memset(dp, 0, sizeof(dp)); 22 double res2 = 1; 23 for(int i = 1; i <= t; i++) 24 { 25 double temp = 1; 26 for(int j = 1; j <= m; j++) 27 { 28 scanf("%lf", &an[i][j]); 29 temp *= (1 - an[i][j]); 30 } 31 res2 *= (1 - temp); 32 } 33 for(int i = 1; i <= t; i++) 34 { 35 sn[i][0][0] = 1; 36 } 37 for(int i = 1; i <= t; i++) 38 { 39 for(int j = 1; j <= m; j++) 40 { 41 for(int k = 0; k <= n; k++) 42 { 43 if(k == 0) 44 sn[i][j][k] = (1 - an[i][j]) * sn[i][j - 1][k]; 45 else 46 { 47 sn[i][j][k] = sn[i][j - 1][k - 1] * an[i][j] + sn[i][j - 1][k] * (1 - an[i][j]); 48 } 49 } 50 } 51 } 52 for(int i = 1; i <= t; i++) 53 { 54 for(int j = 1; j < n; j++){ 55 dp[i][n] += sn[i][m][j]; 56 } 57 } 58 double res = 1; 59 for(int i = 1; i <= t; i++) 60 res *= dp[i][n]; 61 printf("%.3lf ", res2 - res); 62 } 63 return 0; 64 }