【POJ 2151】Check the difficulty of problems

来源:互联网 发布:高精度手机gps软件 编辑:程序博客网 时间:2024/06/04 18:15

【POJ 2151】Check the difficulty of problems

明明是道概率dp 训练计划里却赤果果放在了hash+二分里。。。。shenmegui
不过强行把概率dp给整了出来。。自己瞎捣鼓居然捣鼓出来了
T支队伍每支队伍都要解M道题 问每只队伍至少解1道并且解答最多的队伍要解N道以上的概率是多少
直接做很难 可以用补集
P(AllTeam >= 1 && MaxTeam >= N) = 1 - P(HasTeam < 1 || AllTeam < N)
开一个数组 存放对应解题数的概率

for i 1->T                                 //第i队伍{     for j 1->M                            //第j题     {        for k j->0                         //j限制了最大解题数             if(k==0) dp[k] *= (1-p[j]);    //1题没解 = 1-p[j]累乘            else dp[k] = dp[k]*(1-p[j]) + dp[k-1]*p[j]    }}

dp后分别找出HasTeam<1 || AllTeam < N的概率即可求出答案
我们发现 两边存在重叠 可以合并为P(HasTeam < 1) + P(0 < AllTeam < N)
0 < AllTeam < N 就是所有队伍1~N+1的所有组合乘积
假设T = 2 N = 4
team1解决1题概率为a 解决两题为b 三题为c
team2解决1题概率为A 解决两题为B 三题为C
显然 P(0 < AllTeam < N) = a*A + b*A + c*A + a*B + b*B + c*B + a*C + b*C + c*C = (a+b+c)*(A+B+C)
同样对于多个队伍来说也是如此 故可推出 P(0 < AllTeam < N) = 每只队伍各自解1~n-1个题的累加 然后把每只队伍各自的加和累乘
求P(HasTeam < 1)又会发现 如果和上面一样求法会出现重叠 p1*p2在后面又会出现p2*p1 所以同样再用一次补集 P(HasTeam < 1) = 1 - P(NoTeam < 1)
P(NoTeam < 1) = team 1->T (1-dp[0])累乘
准备工作都做完后便可直接求出结果
P(AllTeam >= 1 && MaxTeam >= N)
= 1 - P(HasTeam < 1 || AllTeam < N)
= 1 - (P(HasTeam < 1) + P(1 < AllTeam < N))
= 1 - ((1 - P(NoTeam < 1)) + P(1 < AllTeam < N))
= P(NoTeam < 1) - P(1 < AllTeam < N)

给的时间范围时2000ms 本想开个输入外挂强行装一发。。结果写的太搓没过TOT 哪位大牛帮忙瞅瞅~

代码如下:

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;double pm[1111][33],dp[33];double read(){    double x = 0,p = 0.1;    char ch = ' ';    while(ch < '0' || ch > '9') ch = getchar();    while(ch >= '0' && ch <= '9') x = x*10+ch-'0',ch = getchar();    if(ch != '.') return x;    ch = getchar();    while(ch >= '0' && ch <= '9') x += (ch-'0')*p,p*=0.1,ch = getchar();    return x;}int main(){    int i,j,k,m,n,t;    double p,sd,zer;    while(~scanf("%d %d %d",&m,&t,&n) && m)    {        p = zer = 1;        for(i = 0; i < t; ++i)        {            for(j = 0; j < m; ++j) scanf("%lf",&pm[i][j]);//pm[i][j] = read();        }        for(i = 0; i < t; ++i)        {            memset(dp,0,sizeof(dp));            sd = 0;            dp[0] = 1;            for(j = 0; j < m; ++j)            {                for(k = min(j+1,n+1); k >= 0; --k)                {                    if(!k) dp[k] *= (1-pm[i][j]);                    else dp[k] = (1-pm[i][j])*dp[k]+dp[k-1]*pm[i][j];                }            }            for(j = 1; j < n; ++j) sd += dp[j];            p *= sd;            zer *= 1-dp[0];        }        printf("%.3lf\n",zer-p);    }    return 0;}
0 0
原创粉丝点击