poj 2151 Check the difficulty of problems 概率dp

Check the difficulty of problems
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 4951   Accepted: 2167

Description

Organizing a programming contest is not an easy job. To avoid making the problems too difficult, the organizer usually expect the contest result satisfy the following two terms: 
1. All of the teams solve at least one problem. 
2. The champion (One of those teams that solve the most problems) solves at least a certain number of problems. 

Now the organizer has studied out the contest problems, and through the result of preliminary contest, the organizer can estimate the probability that a certain team can successfully solve a certain problem. 

Given the number of contest problems M, the number of teams T, and the number of problems N that the organizer expect the champion solve at least. We also assume that team i solves problem j with the probability Pij (1 <= i <= T, 1<= j <= M). Well, can you calculate the probability that all of the teams solve at least one problem, and at the same time the champion team solves at least N problems? 

Input

The input consists of several test cases. The first line of each test case contains three integers M (0 < M <= 30), T (1 < T <= 1000) and N (0 < N <= M). Each of the following T lines contains M floating-point numbers in the range of [0,1]. In these T lines, the j-th number in the i-th line is just Pij. A test case of M = T = N = 0 indicates the end of input, and should not be processed.

Output

For each test case, please output the answer in a separate line. The result should be rounded to three digits after the decimal point.

Sample Input

2 2 2
0.9 0.9
1 0.9
0 0 0

Sample Output

0.972

Source

POJ Monthly,魯小石

題意:

ACM比賽中,共M道題,T個隊,pij表示第i隊解出第j題的概率
問 每隊至少解出一題且冠軍隊至少解出N道題的概率。


思路:

這道題分兩部,首先考慮所有隊都至少出一題的概率,再求所有隊出題數都在1到n-1範圍的概率,兩者相減就是答案。

第一部分首先考慮每隊至少出一題的概率,這個好說,用1減去該隊一題不出的情況就是該隊至少一題的情況,

最後乘到一起就是所有隊都至少出一題的情況。

第二部分,考慮所有出題隊出題數都爲1~n-1的概率,這一部分要使用概率dp

設dp[i][j][k]爲第i個隊伍前j道題做出k道的概率,則狀態方程顯而易見:

dp[i][j][k]=p*dp[i][j-1][k-1]+(1-p)*dp[i][j-1][k]; p爲做出第j道題的概率

最後一求和就是第二部分的概率,用第一部分的減去第二部分的就是答案了。

其中dp可以用滾動數組優化,能大大節約空間,反正過了,也懶得寫了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N=1005;
const double eps=1e-5;
int n,m,t;
double a[N][33],ansp;
double dp[N][33][33];
void solve(){
    double s=1;
    for(int i=1;i<=t;i++){
        double p=1;
        for(int j=1;j<=m;j++){
            scanf("%lf",&a[i][j]);
            p*=1-a[i][j];
        }
        s*=1-p;//s爲所有人都至少出一題的概率
    }
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=t;i++){
        dp[i][0][0]=1;
        for(int j=1;j<=m;j++){
            for(int k=0;k<=j;k++){
                if(k>0)dp[i][j][k]=dp[i][j-1][k-1]*a[i][j];
                dp[i][j][k]+=dp[i][j-1][k]*(1-a[i][j]);
            }
        }
    }
    double ans=1;
    for(int i=1;i<=t;i++){
        double sum=0;
        for(int j=1;j<n;j++){
            sum+=dp[i][m][j];
        }
        ans*=sum;
    }
    ans=s-ans;
    printf("%.3f\n",ans);
}
int main()
{
    while(scanf("%d%d%d",&m,&t,&n),m||t||n){
        solve();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章