POJ 2151 Check the difficulty of problems(概率DP)

http://poj.org/problem?id=2151

题意:
ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率
问 每队至少解出一题且冠军队至少解出N道题的概率。

分析:

解析:DP
设dp[i][j][k]表示第i个队在前j道题中解出k道的概率
则:
dp[i][j][k]=dp[i][j-1][k-1]*p[j][k]+dp[i][j-1][k]*(1-p[j][k]);
先初始化算出dp[i][0][0]和dp[i][j][0];
设s[i][k]表示第i队做出的题小于等于k的概率
则s[i][k]=dp[i][M][0]+dp[i][M][1]+``````+dp[i][M][k];

则每个队至少做出一道题概率为P1=(1-s[1][0])*(1-s[2][0])*```(1-s[T][0]);
每个队做出的题数都在1~N-1的概率为P2=(s[1][N-1]-s[1][0])*(s[2][N-1]-s[2][0])*```(s[T][N-1]-s[T][0]);

最后的答案就是P1-P2

这题不容易啊 , dp的部分还好想啊,可是把答案转化为P1-P2这一步就是核心了,只能说TQL

#include<stdio.h>
#include<string.h>

double dp[1010][31][31],p[1010][31],S[1010][31];

int main()
{
    int n,m,T;
    while(~scanf("%d%d%d",&m,&n,&T)){
        if(m==0&&n==0&&T==0) break;
    memset(dp,0,sizeof(dp));
    memset(S,0,sizeof(S));
    for(int i=1 ; i<=n ; i++)
    for(int j=1 ; j<=m ; j++)
    scanf("%lf",&p[i][j]);

    //dp[i][j][k]:第i个队伍前j道题目完成了k个

    for(int i=1 ; i<=n ; i++)
    {dp[i][0][0]=1;
        for(int j=1 ; j<=m ; j++)
        {
            dp[i][j][0]=dp[i][j-1][0]*(1-p[i][j]);
        }
    }
    for(int i=1 ; i<=n ; i++)
    {
        for(int j=1 ; j<=m ; j++)
        {
            for(int 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]);
            }
        }
    }
   //  S[i][M]:第i队伍完成M道题的概率
     for(int i=1 ; i<=n ; i++)
     {
         S[i][0]=dp[i][m][0];
         for(int j=1 ; j<=m ; j++)
         {
             S[i][j]=S[i][j-1]+dp[i][m][j];
         }
     }
     double ans1=1;
     for(int i=1 ; i<=n ; i++)
     {
             ans1*=(1-S[i][0]);
     }
     double ans2=1;
     for(int i=1 ; i<=n ; i++)
     {
         ans2*=(S[i][T-1]-S[i][0]);
     }
     printf("%.3f
",ans1-ans2);
    }
}
View Code
原文地址:https://www.cnblogs.com/shuaihui520/p/11154651.html