1. 程式人生 > >POJ 2151 Check the difficulty of problems:概率dp【至少】

POJ 2151 Check the difficulty of problems:概率dp【至少】

統計 () and res -s code courier max space

題目鏈接: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\n",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 }

POJ 2151 Check the difficulty of problems:概率dp【至少】