首页 > 代码库 > poj 2151 Check the difficulty of problems (dp,概率)

poj 2151 Check the difficulty of problems (dp,概率)

链接:poj 2151

题意:比赛中有M道题,T个参赛队,pij表示第i队解出第j题的概率,

求每队至少解出一题,且冠军队至少解出N道题的概率

分析:要求每队至少解出一题,且冠军队至少解出N道题的概率

则原来的所求的概率可以转化为:

每队均至少做一题的概率P1 减去 每队做题数均在1到N-1之间的概率P2

设dp[i][j][k]表示第i队在前j道题解出k道题的概率

dp[i][j][k]=dp[i][j-1][k-1]*pij+dp[i][j-1][k]*(1-pij)

设sum[i][j]为第i队至多解出j道题的概率

则 sum[i][j]=dp[i][M][0]+dp[i][M][1]+...+dp[i][M][j]

sum[i][M]-sum[i][0]为第i队至少解出1道题的概率

sum[i][N-1]-sum[i][0]为第i队解出 [1,N-1]道题的概率


#include<stdio.h>
#include<string.h>
double p[1005][32],dp[32][32],sum[32],p1,p2;
int main()
{
    int t,m,n,i,j,k;
    while(scanf("%d%d%d",&m,&t,&n)!=EOF){
        if(t==0&&m==0&&n==0)
            break;
        for(i=1;i<=t;i++)
            for(j=1;j<=m;j++)
                scanf("%lf",&p[i][j]);
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
        p1=p2=1.0;
        for(i=1;i<=t;i++){
            dp[0][0]=1.0;
            for(j=1;j<=m;j++){
                dp[j][0]=dp[j-1][0]*(1-p[i][j]);
                for(k=1;k<=j;k++)
                    dp[j][k]=dp[j-1][k]*(1-p[i][j])+dp[j-1][k-1]*p[i][j];
            }
            sum[0]=dp[m][0];
            for(j=1;j<=m;j++)
                sum[j]=sum[j-1]+dp[m][j];
            p1*=(sum[m]-sum[0]);
            p2*=(sum[n-1]-sum[0]);
        }
        printf("%.3lf\n",p1-p2);
    }
    return 0;
}



poj 2151 Check the difficulty of problems (dp,概率)