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>








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