POJ 2151 Check the difficulty of problems

这道题是一道概率DP题,好难啊!!!

题目大体是这个意思:

ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率

问 每队至少解出一题且冠军队至少解出N道题的概率(冠军可以并列)。

看题解看懂的,表示大牛们真的好强。

因为冠军不一定有多少,所以这题需要转化为:

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


再次感谢大牛可以让我盗图,本事不够只能这样了,慢慢学吧。

下面是代码:

#include <stdio.h>
#include <string.h>
double p[1003][33],dp[1003][33][33],s[1003][33];
int main()
{
    int m,t,n;
    while(scanf("%d%d%d",&m,&t,&n),m||t||n)
    {
        int i,j,k;
        double p1=1,p2=1,temp;
        for(i=1; i<=t; i++)
        {
            for(j=1; j<=m; j++)
            {
                scanf("%lf",&p[i][j]);
            }
        }
        memset(dp,0.0,sizeof(dp));
        memset(s,0.0,sizeof(s));
        for(i=1; i<=t; i++) //逐队枚举
        {
            dp[i][0][0]=1.0;
            for(j=1; j<=m; j++)
            {
                dp[i][j][0]=dp[i][j-1][0]*(1-p[i][j]); //初始化每队前J题都答不上来的概率
            }
            for(j=1; j<=m; j++)
            {
                for(k=1; k<=j; k++)
                {
                    dp[i][j][k] = dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1-p[i][j]);
                    /**第I队当解到第J题时解出K个题的概率是解前J-1个题时解出K-1个的概率乘以解出第
                     J题的概率加上解前J-1个题时解出K个的概率乘以第J个题没解出的概率*/
                }
            }
            s[i][0]=dp[i][m][0];//最后第I队解0个题的概率是dp[i][m][0];及第I队做M题做出0道的概率。
            for(k=1; k<=m; k++)
            {
                s[i][k]=s[i][k-1]+dp[i][m][k];
                //第I队解出K道题的概率是第I队解出K-1道题的概率加上及第I队做M题做出K道的概率。
            }
        }
        //p1为每队均至少做一题的概率,p2为每队做题数均在1到N-1之间的概率。
        for(i=1; i<=t; i++)
        {
            p1*=(s[i][m]-s[i][0]);
        }
        for(i=1; i<=t; i++)
        {
            p2*=(s[i][n-1]-s[i][0]);
        }
        printf("%.3lf\n",p1-p2);
    }
    return 0;
}


posted @ 2013-08-15 15:50  、小呆  阅读(113)  评论(0编辑  收藏  举报