题目链接:http://poj.org/problem?id=2151
题意:
一次ACM比赛,有t支队伍,比赛共m道题。
第i支队伍做出第j道题的概率为p[i][j].
问你所有队伍都至少做出一道,并且有队伍做出至少n道的概率。
题解:
关于【至少】问题的表示。
对于每一支队伍:
mst[i][j] = P(第i支队伍做出至多j道题)
则 P(第i支队伍做出至少j道题) = 1 - mst[i][j-1]
对于所有队伍:
P(所有队伍至少答出一题) = ∏ (1 - mst[i][0])
P(所有队伍答题数在1到n-1) = ∏ (mst[i][n-1] - mst[i][0])
所以答案:
P(所有队伍至少答出一题,且有队伍做出至少n道) = P(所有队伍至少答出一题) - P(所有队伍答题数在1到n-1)
所以求mst数组好啦~~~
dp[i][j][k] = probability
i:第i支队伍
j:考虑到前j道题(包含j)
k:恰好做出k道
所以 mst[i][j] = sigma(dp[i][m][0 to j])
怎么求dp数组呢:
转移:dp[i][j][k] = dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1-p[i][j])
边界:dp[i][0][0] = 1, others = 0
所以这道题:先求dp,再求mst,最后统计ans。
AC Code:
1 // state expression: 2 // dp[i][j][k] = probability 3 // i: ith team 4 // j: jth question and before 5 // k: solved k questions 6 // mst[i][j] 7 // i: ith team 8 // j: all the teams solved at most j questions 9 // 10 // find the answer: 11 // P(all 1 to m) - P(all 1 to n-1) 12 // 13 // transferring: 14 // dp[i][j][k] = dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1-p[i][j]) 15 // 16 // boundary: 17 // dp[i][0][0] = 1 18 // others = 0 19 // 20 // calculate: 21 // mst[i][j] = sigma dp[i][m][0 to j] 22 // P1 = pi (1 - mst[i][0]) 23 // P2 = pi (mst[i][n-1] - mst[i][0]) 24 // 25 // step: 26 // 1) cal dp 27 // 2) cal mst 28 // 3) cal ans 29 #include <iostream> 30 #include <stdio.h> 31 #include <string.h> 32 #define MAX_T 1005 33 #define MAX_N 35 34 #define MAX_M 35 35 36 using namespace std; 37 38 int n,m,t; 39 double p1,p2; 40 double p[MAX_T][MAX_M]; 41 double dp[MAX_T][MAX_M][MAX_M]; 42 double mst[MAX_T][MAX_M]; 43 44 void read() 45 { 46 for(int i=1;i<=t;i++) 47 { 48 for(int j=1;j<=m;j++) 49 { 50 cin>>p[i][j]; 51 } 52 } 53 } 54 55 void cal_dp() 56 { 57 memset(dp,0,sizeof(dp)); 58 for(int i=1;i<=t;i++) 59 { 60 dp[i][0][0]=1; 61 for(int j=1;j<=m;j++) 62 { 63 for(int k=0;k<=m;k++) 64 { 65 if(k-1>=0) dp[i][j][k]+=dp[i][j-1][k-1]*p[i][j]; 66 dp[i][j][k]+=dp[i][j-1][k]*(1-p[i][j]); 67 } 68 } 69 } 70 } 71 72 void cal_mst() 73 { 74 // mst[i][j] = sigma dp[i][m][0 to j] 75 memset(mst,0,sizeof(mst)); 76 for(int i=1;i<=t;i++) 77 { 78 for(int j=0;j<=m;j++) 79 { 80 for(int k=0;k<=j;k++) 81 { 82 mst[i][j]+=dp[i][m][k]; 83 } 84 } 85 } 86 } 87 88 void cal_ans() 89 { 90 // P1 = pi (1 - mst[i][0]) 91 // P2 = pi (mst[i][n-1] - mst[i][0]) 92 p1=1.0; 93 p2=1.0; 94 for(int i=1;i<=t;i++) 95 { 96 p1*=(1-mst[i][0]); 97 p2*=(mst[i][n-1]-mst[i][0]); 98 } 99 } 100 101 void solve() 102 { 103 cal_dp(); 104 cal_mst(); 105 cal_ans(); 106 } 107 108 void print() 109 { 110 printf("%.3f ",p1-p2); 111 } 112 113 int main() 114 { 115 while(cin>>m>>t>>n) 116 { 117 if(m==0 && t==0 && n==0) break; 118 read(); 119 solve(); 120 print(); 121 } 122 }