• 动态规划——概率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);}
          }
    }
  • 相关阅读:
    不常用的cmd命令
    js获取宽度
    Marshaling Data with Platform Invoke 概览
    Calling a DLL Function 之三 How to: Implement Callback Functions
    Marshaling Data with Platform Invoke 之四 Marshaling Arrays of Types
    Marshaling Data with Platform Invoke 之一 Platform Invoke Data Types
    Marshaling Data with Platform Invoke 之三 Marshaling Classes, Structures, and Unions(用时查阅)
    Calling a DLL Function 之二 Callback Functions
    WCF 引论
    Marshaling Data with Platform Invoke 之二 Marshaling Strings (用时查阅)
  • 原文地址:https://www.cnblogs.com/rhythmic/p/5348209.html
Copyright © 2020-2023  润新知