POj 2151 Check the difficulty of problems 概率DP

来源:互联网 发布:76.164.232.68indx.php 编辑:程序博客网 时间:2024/06/11 04:51

题意:ACM比赛中有M道题,T个队,P[i][j]代表第i个队解出第j题的概率,问每队至少解出1道并且冠军队至少解出N道的概率,注意:冠军队不仅只有一支

所求概率可以转化成:每队至少做出1道题的概率p1 减去 每队做题数均在1--N-1的概率p2

利用 dp[i][j][k] 表示第 i 队在前 j 题中做出 k 题的概率

        s[i][j] 表示第i 队在前M题中做出j题的概率

       s[i][k]=dp[i][M][0]+dp[i][M][1]+.....+dp[i][M][k];

       则s[i][M]表示第i队的做出全部题目的概率,s[i][0]表示第i 队一题也做不出来的概率

===>s[i][M]-s[i][0]表示第i队至少做出一道题的概率p1

===>s[i][N-1]-s[i][0]表示第i队做出题数在1-N-1的概率p2

代码:

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>#include<map>#include<queue>#include<vector>#include<string>using namespace std;const int M=150005;double dp[1005][31][31];double s[1005][31];double p[1005][31];int main(){    int m,t,n;    while(cin>>m>>t>>n)    {        if(!m&&!t&&!n)break;        memset(dp,0,sizeof(dp));        memset(s,0,sizeof(s));        for(int i=1;i<=t;i++)        {            for(int j=1;j<=m;j++)            {                scanf("%lf",&p[i][j]);            }        }        for(int i=1;i<=t;i++)        {            dp[i][0][0]=1.0;            for(int j=1;j<=m;j++)            {                dp[i][j][0]=dp[i][j-1][0]*(1-p[i][j]);            }            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][0]=dp[i][m][0];            for(int j=1;j<=m;j++)            {                s[i][j]=s[i][j-1]+dp[i][m][j];            }        }        double p1=1.0,p2=1.0;        for(int i=1;i<=t;i++)        {            p1*=(s[i][m]-s[i][0]);        }        for(int i=1;i<=t;i++)        {            p2*=(s[i][n-1]-s[i][0]);        }        printf("%.3f\n",p1-p2);    }    return 0;}