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

来源:互联网 发布:matlab三维数组画图 编辑:程序博客网 时间:2024/06/04 23:22

      这道题的大概意思就是说有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;}