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

      这道题的大概意思就是说有n支队伍,t道题,并且给你每支队伍答对每道题的概率,然后问你的就是使所有队伍都过至少一道题,并且第一名的队伍答对至少m道题的概率是多少。

      我们先看下如何解决一个队伍的情况,比如说,有t道题,那么我们如何求答对k(t>=k>=0)道题的概率呢?我们考虑使用dp进行递推!定义dp[i][j]表示前i道题中答对j道题的概率,这个时候我们就可以很简单的写出状态转移方程如下:dp[i][j]=dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i],其中p[i]表示答对第i道题的概率,得到状态转移方程之后就好写了。

      那么对于题目中的问题如何解答呢?题目中问的是要使每一支队伍答对的题数大于等于1,并且冠军的题数一定要大于等于m,我们可以求出所有球队过题数大于等于1的概率,然后减去所有队伍过题数都收介于1和m-1之间的概率就是题目中要求的概率。知道这些,这道题就好做了。

附上我的代码给参考下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int Max=1002;
double dp[Max][32][32];
double p[Max][32];
int main()
{
    int n,m,t;
    while(scanf("%d %d %d",&t,&n,&m))
    {
        if(n==0&&t==0&&m==0)
            break;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=t;j++)
                scanf("%lf",&p[i][j]);
        }
        for(int k=1;k<=n;k++)
        {
            dp[k][0][0]=1.0;
            for(int i=1;i<=t;i++)
            {
                for(int j=i+1;j<=t;j++)
                {
                    dp[k][i][j]=0.0;
                }
            }
        }
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=t;i++)
            {
                for(int j=0;j<=i;j++)
                {
                    dp[k][i][j]=dp[k][i-1][j]*(1-p[k][i]);
                    if(j>0)
                        dp[k][i][j]+=dp[k][i-1][j-1]*p[k][i];
               //     printf("%d %d %d %.2lf\n",k,i,j,dp[k][i][j]);
                }
            }
        }
        double a=1.0,b=1.0;
        for(int k=1;k<=n;k++)
        {
            a*=(1.0-dp[k][t][0]);
            double temp=0.0;
            for(int i=1;i<m;i++)
            {
                temp+=dp[k][t][i];
            }
            b*=temp;
        }
        printf("%.3f\n",a-b);
    }
    return 0;
}


你可能感兴趣的:(简单概率DP(POJ 2151 Check the difficulty of problems))