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;
}


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