CodeForces 148D Bag of mice (经典概率dp)

本文介绍了一个利用动态规划(DP)解决抓老鼠游戏中概率计算的问题。具体问题为:袋子里有W只白鼠和B只黑鼠,王妃与龙依次抓取,先抓到白鼠者获胜,若均未抓到则龙胜。文章详细解释了状态转移方程,并给出了完整的C++代码实现。

传送门

我写的比较搓,是用来自己参考的,各位大佬们
我是从这位巨巨的博客上看到思路的
真的对我理解dp很有帮助
巨巨的传送门

题目大意(copy的 ^)
原来袋子里有w只白鼠和b只黑鼠
龙和王妃轮流从袋子里抓老鼠。谁先抓到白色老鼠谁就赢。
王妃每次只抓一只老鼠,但是龙每次抓完一只老鼠之后会有一只老鼠跑出来。
每次抓老鼠和跑出来的老鼠都是随机的。
如果两个人都没有抓到白色老鼠则龙赢。王妃先抓。
问王妃赢的概率。

这题状态很好找,就是dp[i][j]为白老鼠i个,黑老鼠j个王妃赢得概率
然后就是怎么转移

首先我们考虑公主一上来就拿到白老鼠的情况就是dp[i][j] += i/(i+j)
然后,考虑转移的情况
就是公主抓了一个黑的,龙抓了一个黑的,跑了一个黑的 即 dp[i][j] += j/(i+j) * j-1/(i+j-1) * j-2/(i+j-2) * dp[i][j-3]
还有就是公主抓了一个黑的,龙抓了一个黑的,跑了一个白的 即dp[i][j] += j/(i+j) * j-1/(i+j-1) * i/(i+j-2) * dp[i-1][j-2]

还有一种情况,就是公主抓了一只黑老鼠,龙抓了白的,这样公主输了,就不能转移了

边界很简单,dp[i][0] = 1,dp[0][j] = 0;
我一开始不是很能理解转移的那两种情况,因为我认为之前的那个状态不是已经公主赢了吗,为什么还能转移,其实是我理解错了,dp[i][j]是对应这个状态能赢的概率,不是我们所求的概率,所以我们还需要去转移,但是思路上还是比较难理解。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;

double dp[1010][1010];

int main()
{
    int w,b;
    scanf("%d%d",&w,&b);
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=w;i++) dp[i][0] = 1;
    for(int i=0;i<=b;i++) dp[0][i] = 0;

    for(int i=1;i<=w;i++){
        for(int j=1;j<=b;j++){
            dp[i][j] += (double)i/(i+j);
            if(j>=3){
                dp[i][j] += (double)j/(i+j) * ((double)(j-1)/(i+j-1)) * ((double)(j-2)/(i+j-2)) * dp[i][j-3];
            }
            if(j>=2){
                dp[i][j] += (double)j/(i+j) * (double)(j-1)/(i+j-1) * ((double)i/(i+j-2)) * dp[i-1][j-2];
            }
        }
    }

    printf("%.9lf\n",dp[w][b]);
    return 0;
}

加油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值