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

傳送門

我寫的比較搓,是用來自己參考的,各位大佬們
我是從這位巨巨的博客上看到思路的
真的對我理解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;
}

加油

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章