• 【POJ2151】Check the difficulty of problems


    题意

       某场比赛有M道问题,T支队伍,和数字N给出每支队伍解决每道问题的概率。 问这场比赛满足下面两个条件的概率

       1.每支队伍至少做出一道题

       2.冠军队至少做出N道题。

    分析

     条件2是不是可以转化为 至少有一支队做出N道及以上道题。

     这个题主要是概率,其次才是dp,而且好像不算概率DP。

     我们来倒推一下。

     设p2为每支队伍做出来的题数都在(1-N-1)的概率。p1为每只队伍至少做出来一道题的概率。那么答案就是p1-p2。

     然后我们再来想怎么求p1和p2。设s[i][j]为第i支队伍做出来题数小于等于j的概率。那么

     p1=(1-s[1][0])*(1-s[2][0])*...*(1-s[T][0]).

     p2=(s[1][N-1]-s[1][0])*(s[2][N-1]-s[2][0])*...*(s[T][N-1]-s[T][0])。

     然后再往前推。s[i][j]该怎么求?

     我们发现队伍与队伍之间没有关系,于是我们可以每支队伍都通过dp求解。对于每支队伍k

      我们令f[i][j]为前i个问题中做出来j个题的概率 f[i][j]=f[i-1][j]*(1-P[k][j])+f[i-1][j-1]*P[k][j];

      然后 s[k][j]=sum(f[M][l])(0<=l<=j)

      就是这个样子。

      这个题的DP是最基础的,但是概率那里我觉得不是特别好想。。(可能因为我菜吧···)

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 const int maxn=1000+100;
     8 const int maxm=50;
     9 int M,T,N;
    10 double P[maxn][maxm];
    11 double f[maxm][maxm],s[maxn][maxm];
    12 int main(){
    13     while(scanf("%d%d%d",&M,&T,&N)!=EOF&&(M||T||N)){
    14         memset(P,0,sizeof(P));
    15         for(int i=1;i<=T;i++){
    16             for(int j=1;j<=M;j++){
    17                 scanf("%lf",&P[i][j]);
    18             }
    19             memset(f,0,sizeof(f));
    20             f[0][0]=1.0;
    21             for(int j=1;j<=M;j++){
    22                 for(int k=0;k<=j;k++){
    23                     if(k==0)
    24                       f[j][k]=f[j-1][k]*(1-P[i][j]);
    25                     else
    26                      f[j][k]=f[j-1][k-1]*P[i][j]+f[j-1][k]*(1-P[i][j]);
    27                 }
    28             }
    29             double sum=0;
    30             for(int j=0;j<=M;j++){
    31                 sum+=f[M][j];
    32                 s[i][j]=sum;
    33             }
    34         }
    35         double p1,p2;
    36         p1=p2=1.0;
    37         for(int i=1;i<=T;i++){
    38             p1*=(1-s[i][0]);
    39         }
    40         for(int i=1;i<=T;i++){
    41             p2*=(s[i][N-1]-s[i][0]);
    42         }
    43         double ans=p1-p2;
    44         printf("%.3f
    ",ans);
    45     }
    46 return 0;
    47 }
    View Code
  • 相关阅读:
    消息队列RocketMQ版最佳实践订阅关系一致
    Java8 stream、List forEach 遍历对象 List 对某一字段重新赋值
    SQL的嵌套查询与连接查询
    Xshell7 个人可以申请免费使用正版
    @NotEmpty、@NotBlank、@NotNull 区别和使用
    List集合日常总结
    Time Zone(时区)
    Arrays.asList() 和Collections.singletonList()的区别
    GitBash生成SSH密钥
    Mysql中用SQL增加、删除、修改(包括字段长度/注释/字段名)总结
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9097252.html
Copyright © 2020-2023  润新知