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

来源:互联网 发布:深圳有名的公司 知乎 编辑:程序博客网 时间:2024/06/08 04:08

传送门

我写的比较搓,是用来自己参考的,各位大佬们
我是从这位巨巨的博客上看到思路的
真的对我理解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 longusing 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;}

加油

0 0
原创粉丝点击