• 动态规划——概率dp


      所谓概率dp,用动态规划的思想找到一个事件中可能发生的所有情况,然后找到符合要求的那些情况数,除以总数便可以得到符合要求的事件发生的概率。其核心思想还是通过dp来得到事件发生的所有情况,很类似在背包专题中我们提及的组合记数问题。

      我们通过具体的实例来体会概率dp这类问题。(Problem source : Light OJ 1064)

    Description

    n common cubic dice are thrown. What is the probability that the sum of all thrown dice is at least x?

    Input

    Input starts with an integer T (≤ 200), denoting the number of test cases.

    Each test case contains two integers n (1 ≤ n < 25) and x (0 ≤ x < 150). The meanings of n and x are given in the problem statement.

    Output

    For each case, output the case number and the probability in 'p/q' form where p and q are relatively prime. If q equals 1 then print p only.

      题目大意:给出整数n、x,同时抛掷n个筛子,求解点数和大于x情况出现的概率。

      数理分析:我们更加细化的模拟这个抛掷筛子的过程,从第一个开始抛掷,不难发现有6种情况,然后抛掷第二个筛子,基于第一个筛子的6种情况,我们可以得到抛完第二个筛子后所有的情况,然后抛掷第三个筛子……

      我们设置二维数组dp[i][j]表示抛掷i个筛子后,点数为j的情况数,我们容易得到如下的状态转移方程:

                 dp[i][j] = dp[i-1][j-k]  (k∈[1,6])

      基于这个状态转移方程,我们不难得到第n个筛子抛掷后所有可能的情况的总数和符合要求的总数,这里根据题目的输出要求,需要是分数的最简形式,我们只需调用欧几里得算法求出最大公约数然后化简即可,而对于概率为0和1的特殊情况,设置条件进行判断即可。

      参考代码如下。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    long long n , m , dp[30][155];
    
    long long gcd(long long a , long long b)
    {
         return b == 0 ? a:gcd(b,a%b);
    }
    
    int main()
    {
          int i , j , k , cas , T;
          scanf("%d",&T);
          for(cas = 1;cas <= T;cas++)
          {
                 scanf("%lld%lld",&n,&m);
                 memset(dp , 0 , sizeof(dp));
                 dp[0][0] = 1;
                 for(i = 1;i <= n;i++)
                 {
                      for(j = 1;j < 155;j++)
                      {
                           for(k = 1;k <= 6 && j-k >= 0;k++)
                               dp[i][j] += dp[i-1][j-k];
                      }
                 }
                 long long p , q , g;
                    q = p = 0;
                    for(int i = 1;i < 155;i++)
                    {
                        p += dp[n][i];
                        if(i >= m)
                           q += dp[n][i];
                    }
                    g = gcd(p , q);
                    p/=g;
                    q/=g;
                    printf("Case %d: ",cas);
                    if(q == 0)   printf("0
    ");
                    else if (q == p) printf("1
    ");
                    else  {printf("%lld/%lld
    ",q,p);}
          }
    }
  • 相关阅读:
    codeforces 724G
    P4151 [WC2011]最大XOR和路径 线性基
    2018-2019 ACM-ICPC, Asia Seoul Regional Contest K TV Show Game 2-sat
    codeforces 1198E Rectangle Painting 2 最小点覆盖
    codeforces847J Students Initiation 网络流
    codeforces863F Almost Permutation 费用流
    codeforces1213F Unstable String Sort 思维
    codeforces1156D 0-1-Tree 并查集
    codeforces1156D 0-1-Tree 换根dp
    错误集合
  • 原文地址:https://www.cnblogs.com/rhythmic/p/5348209.html
Copyright © 2020-2023  润新知