POJ 2151 Check the difficulty of problems [概率DP]

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? 


题意:

一场ACM比赛中,有M道题,T只队伍,现在知道每只队伍对于每一题的AC概率,问全场每个队伍都A出至少一题且至少有一只队伍A了N道题的概率。

范围:

N,M<=30,T<=1000

解法:

画一个维恩图: 假设A表示每个队伍做出至少一题,B表示至少有一只队伍做出N题,那么我们要求解的就是P(A∩B),也就是图中的黄色部分。

但是直接求至少一个这样的概率是比较难求的,需要先求反,然后再根据容斥相减得到。

可以考虑先求解P(A∩~B)也就是红色部分,然后用P(A)-P(A∩~B)得到P(A∩B),其中因为每一个队伍是相互独立的,所以可以单独求,求解方法为dp,dp[I][J]表示前I道题做出J道的概率,转移很简单,略过(可以看代码),然后 连乘每一只队伍的Σdp[1..N-1]就是P(A∩~B),同理求得P(A),然后相减即可得到P(A∩B)

坑点:POJ加速读入会跪...POJ的G++不支持%lf输出,需要用%f...总之就是POJ的judge system 太老了,需要注意一下。


代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdlib.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<bitset>
#pragma comment(linker, "/STACK:1024000000,1024000000")
template <class T>
bool scanff(T &ret){ //Faster Input
    char c; int sgn; T bit=0.1;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    if(c==' '||c=='\n'){ ret*=sgn; return 1; }
    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
    ret*=sgn;
    return 1;
}
#define inf 1073741823
#define llinf 4611686018427387903LL
#define PI acos(-1.0)
#define lth (th<<1)
#define rth (th<<1|1)
#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)
#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)
#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)
#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)
#define mem(x,val) memset(x,val,sizeof(x))
#define mkp(a,b) make_pair(a,b)
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

double p[1001][33];
double dp[33][33];
int n,t,m;

int main(){
    while(scanf("%d%d%d",&m,&t,&n)!=EOF){
        if(m==0&&t==0&&n==0)break;
        //POJ加速读入会跪...
        rep(i,1,t)
            rep(j,1,m)scanf("%lf",&p[i][j]);

        double pa=1.0;
        double pb=1.0;
        rep(k,1,t){
            dp[0][0]=1;
            rep(i,1,m)
                rep(j,0,i){
                    dp[i][j]=dp[i-1][j]*(1.0-p[k][i]);
                    if(j)dp[i][j]+=dp[i-1][j-1]*p[k][i];
                }
            double suma,sumb;
            suma=sumb=0;
            rep(i,1,n-1)sumb+=dp[m][i],suma+=dp[m][i];
            rep(i,n,m)suma+=dp[m][i];
            pa*=suma;
            pb*=sumb;
        }
        //POJ的G++不支持%lf输出...
        printf("%.3f\n",pa-pb);
    }
}<strong>
</strong>








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