概率dp方法及实例

欢迎访问https://blog.csdn.net/lxt_Lucia~~

宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~

摘要

概率DP主要用于求解期望概率等题目,其实和高中概率题的求法也有许多相似之处,能用高中数学知识解决的完全可以用高  中思路直接解决,除此以外,也可以用动态规划求解转移方程,还可以用迭代的方式,有时候就需要比较灵活地运用了。

因此,咱们做概率题的优先考虑顺序为:

1)高中数学直接解决

2)动态规划求解转移方程

3)迭代法

一般来说:求概率是正推,求期望是逆推通过题目可以体会到这点。

下面让我们来举几个栗子具体感受下叭~

实例

 

例1:Discovering Gold LightOj : 1030 

Description

You probably have played the game "Throwing Balls into the Basket". It is a simple game. You have to throw a ball into a basket from a certain distance. One day we (the AIUB ACMMER) were playing the game. But it was slightly different from the main game. In our game we were Npeople trying to throw balls into identical Baskets. At each turn we all were selecting a basket and trying to throw a ball into it. After the game we saw exactly S balls were successful. Now you will be given the value of and M. For each player probability of throwing a ball into any basket successfully is P. Assume that there are infinitely many balls and the probability of choosing a basket by any player is 1/M. If multiple people choose a common basket and throw their ball, you can assume that their balls will not conflict, and the probability remains same for getting inside a basket. You have to find the expected number of balls entered into the baskets after turns.

Input

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

Each case starts with a line containing three integers N (1 ≤ N ≤ 16), M (1 ≤ M ≤ 100) andK (0 ≤ K ≤ 100) and a real number P (0  P ≤ 1)P contains at most three places after the decimal point.

Output

For each case, print the case number and the expected number of balls. Errors less than 10-6will be ignored.

Sample Input

2

1 1 1 0.5

1 1 2 0.5

Sample Output

Case 1: 0.5

Case 2: 1.000000

 

题意:

给定n个格子以及每个格子上的金子数,你从第一个格子出发,每次掷1-6的骰子,根据掷出的值前进。若当前位置 + 掷出的值 > n,则重新掷骰子,直到正好到达第n个格子时游戏结束。求获得最大金子数的期望。

思路:

期望要由后向前推,所以设dp[ i ]为到达 i 个格子获得金子的期望,先初始化dp[ i ] = 第i个格子的金子数。则有dp[ i ] = (dp[ i+1 ] / 6 + ... + dp[ i+6 ] / 6 ) + dp[ i ]。dp[ i ]+=dp[ i+j ] / min ( n-i , 6 ) 的意思是,每次都把第 i 个格子当作目前阶段的起点,那么此时在这个格子的概率为1,期望为dp[ i ] * 1 =dp [ i ],然后再加上前面的min ( n-i , 6 )个可能到达这个格子的期望,这几个格子的概率是相等的,同时需要注意最后的时候到达这个点不足6个的情况,所以就是min ( n-i , 6 )个。直至推到最初起点1的位置,dp[ 1 ] 即为所求。

 

代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

int main()
{
    double dp[1001];
    int i,j,T,z,n;
    scanf("%d",&T);
    for(z=1;z<=T;z++)
    {
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
            scanf("%lf",&dp[i]);
        for(i=n-1;i>=1;i--)
            for(j=1;j<=6;j++)
                dp[i]+=dp[i+j]/min(n-i,6);
        printf("Case %d: %.9lf\n",z,dp[1]);
    }
    return 0;
}

 

 

例2:Throwing Balls into the Baskets ( Light OJ 1317 )

Description

You probably have played the game "Throwing Balls into the Basket". It is a simple game. You have to throw a ball into a basket from a certain distance. One day we (the AIUB ACMMER) were playing the game. But it was slightly different from the main game. In our game we were Npeople trying to throw balls into identical Baskets. At each turn we all were selecting a basket and trying to throw a ball into it. After the game we saw exactly S balls were successful. Now you will be given the value of and M. For each player probability of throwing a ball into any basket successfully is P. Assume that there are infinitely many balls and the probability of choosing a basket by any player is 1/M. If multiple people choose a common basket and throw their ball, you can assume that their balls will not conflict, and the probability remains same for getting inside a basket. You have to find the expected number of balls entered into the baskets after turns.

Input

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

Each case starts with a line containing three integers N (1 ≤ N ≤ 16), M (1 ≤ M ≤ 100) andK (0 ≤ K ≤ 100) and a real number P (0  P ≤ 1)P contains at most three places after the decimal point.

Output

For each case, print the case number and the expected number of balls. Errors less than 10-6will be ignored.

Sample Input

2

1 1 1 0.5

1 1 2 0.5

Sample Output

Case 1: 0.5

Case 2: 1.000000

 

题意:

n个人,m个篮筐,投k轮,每轮所有人均可投一次,每人每次投进的概率均为p,保证n个人扔的球不会碰撞,求k轮投完后投进的个数期望。

 

按照最前面说的步骤,咱们优先考虑高中数学知识直接搞,本题就很好的体现了这个方式。

首先需要注意:n个人扔的球不会碰撞,即每种情况独立,结果互不影响。

 

思路一:

n个人,每轮每人投一次,投k轮,那么就可以看成一个人投了n*k次,每次投进的概率是1/p,那么每次没投进的概率就是(1-p),每轮的期望就是p*1+(1-p)*0=p,那么k轮结束后就是n*k*p。

 

代码一:

#include<stdio.h>
int main()
{
    double p;
    int k,T,z,m,n;
    scanf("%d",&T);
    for(z=1;z<=T;z++)
    {
        scanf("%d%d%d%lf",&n,&m,&k,&p);
        printf("Case %d: %.9lf\n",z,n*k*p);
    }
    return 0;
}

 

 

思路二:

动态规划,根据全期望公式,进行一轮球数量的期望值为ans = dp[ 1 ]*1+dp[ 2 ]*2+...+dp[ n ]*n ,其中dp[ i ]为 i 个人扔中的概率 dp[ i ] = C(n, i) * p^i * (1-p)^(n-i) 最终答案就是ans*k了。

 

代码二:

#include<cstdio>
#include<cstring>

using namespace std;

int main()
{
    int T,z,i,j,n,m,k;
    double p,ans,dp[20],a[20],b[20];
    scanf("%d", &T);
    for(z=1;z<=T;z++)
    {

        scanf("%d %d %d %lf", &n, &m, &k, &p);
        dp[0]=a[0]=b[0]=1;
        for(i=1;i<=n;i++)
        {
            a[i]=a[i-1]*p;
            b[i]=b[i-1]*(1-p);
        }
        for(i=0;i<=n;i++)
        {
            ans=1;
            for(j=1;j<=i;i++)
            {
                ans*=(double)n--;
                ans/=(double)j;
            }
            dp[i]=ans*a[i]*b[n-i];
        }
        ans=0;
        for(i=1;i<=n;i++)
            ans+=dp[i]*(double)i;
        ans*=(double)k;
        printf("Case %d: %.10lf\n",z,ans);
    }
    return 0;
}

 

 

例3:Island of Survival (LightOJ - 1265)

Decription

You are in a reality show, and the show is way too real that they threw into an island. Only two kinds of animals are in the island, the tigers and the deer. Though unfortunate but the truth is that, each day exactly two animals meet each other. So, the outcomes are one of the following

a)      If you and a tiger meet, the tiger will surely kill you.

b)      If a tiger and a deer meet, the tiger will eat the deer.

c)      If two deer meet, nothing happens.

d)      If you meet a deer, you may or may not kill the deer (depends on you).

e)      If two tigers meet, they will fight each other till death. So, both will be killed.

If in some day you are sure that you will not be killed, you leave the island immediately and thus win the reality show. And you can assume that two animals in each day are chosen uniformly at random from the set of living creatures in the island (including you).

Now you want to find the expected probability of you winning the game. Since in outcome (d), you can make your own decision, you want to maximize the probability.

Input

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

Each case starts with a line containing two integers t (0 ≤ t ≤ 1000) and d (0 ≤ d ≤ 1000)where t denotes the number of tigers and d denotes the number of deer.

Output

For each case, print the case number and the expected probability. Errors less than 10-6 will be ignored.

Sample Input

4

0 0

1 7

2 0

0 10

Sample Output

Case 1: 1

Case 2: 0

Case 3: 0.3333333333

Case 4: 1

 

 

题意:

t只老虎,d只鹿,两只老虎相遇会同归于尽,两只鹿相遇会和平相处,你和虎相遇你会死,你和鹿相遇你可以吃它,每天选2只动物放在岛上,求你能活下来的期望。

 

思路:

本题有点坑啊~其实鹿的个数对结果完全没有任何影响,所以你就可以假定第一天老虎就把所有的鹿都已经吃了,然后直接看老虎能不能都同归于尽,然后正好剩下你,如果不可以,老虎数为奇数,那么你必死,生存概率为0即期望也为0,若老虎数为偶数,则生存概率为1/生物总数,生物总数=老虎数+你,嗯没毛病哈哈~注意一下精度~本题当然也可以用动态规划做,不过看起来就麻烦很多了,需要的话可以再自己写一下或者百度一下,这里不再赘述。

 

代码:

#include<stdio.h>
int main()
{
    int tiger,deer,T,z;
    scanf("%d",&T);
    for(z=1;z<=T;z++)
    {
        scanf("%d%d",&tiger,&deer);
        if(tiger%2==1)
            printf("Case %d: 0\n",z);
        else
            printf("Case %d: %.9lf\n",z,(1.0)/(tiger+1)*1.0);
    }
    return 0;
}

 

 

例4:Dice (III)LightOJ 1248

Description

Given a dice with n sides, you have to find the expected number of times you have to throw that dice to see all its faces at least once. Assume that the dice is fair, that means when you throw the dice, the probability of occurring any face is equal.

For example, for a fair two sided coin, the result is 3. Because when you first throw the coin, you will definitely see a new face. If you throw the coin again, the chance of getting the opposite side is 0.5, and the chance of getting the same side is 0.5. So, the result is

1 + (1 + 0.5 * (1 + 0.5 * ...))

= 2 + 0.5 + 0.52 + 0.53 + ...

= 2 + 1 = 3

Input

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

Each case starts with a line containing an integer n (1 ≤ n ≤ 105).

Output

For each case, print the case number and the expected number of times you have to throw the dice to see all its faces at least once. Errors less than 10-6 will be ignored.

Sample Input

5

1

2

3

6

100

Sample Output

Case 1: 1

Case 2: 3

Case 3: 5.5

Case 4: 14.7

Case 5: 518.7377517640

 

题意:

有一个n面的骰子,每次投掷每个面都是等概率出现,求所有面都出现的期望投掷次数。

思路:

套给出的公式,f [ i ]表示已经出现了i个面,还需要投掷的期望次数,f [ n ] = 0 , f [ i ] = i / n * f [ i ] + ( n - i ) / n * f [ i+1 ]  + 1 , 化简后f [ i ] = f [ i+1 ] + n / ( n - i ) , 所以答案就是∑ n / i  ,1 <= i <= n。

 

代码:

#include<stdio.h>
int main()
{
    int n,i,T,z;
    scanf("%d",&T);
    for(z=1;z<=T;z++){
        double sum=0;
        scanf("%d",&n);
        for(i=0;i<=n-1;i++)
            sum+=1+1.0*i/(n-i);
        printf("Case %d: %.9lf\n",z,sum);
    }
    return 0;
}

 

 

 

宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~

 

 

 

猜你喜欢

转载自blog.csdn.net/lxt_Lucia/article/details/81258445
今日推荐