題意:給你w個白色小鼠和b個黑色小鼠,把他們放到袋子裏,princess先取,dragon後取,princess取的時候從剩下的當當中任意取一個,dragon取得時候也是從剩下的時候任取一個,可是取完以後會隨機跳出來一個。取到每一個小鼠的機率是同樣的,跳出的也是同樣的。先取到白色的小鼠贏,問最後princess能贏的機率。spa
思路:機率dp,若是把princess能贏的分紅兩種狀況,那麼這個題就是遞推了,我是用記憶化搜索寫的。首先,用dp[i][j]表示袋子當中還有i個白色的,j個黑色的princess能取贏的機率。那麼有兩種狀況:code
1.這一步能取贏,那麼就是直接取到白色的,機率爲i/(i+j);blog
2.這一步取不贏,那麼當前必定是取到黑色的,由於最後要讓princess贏,因此,接着dragon也取不贏,如今還有一個問題是,跳出的小鼠的顏色,那麼又分爲兩種狀況:string
1). 跳出的爲白色的。機率就是j/(i+j)*(j-1)/(i+j-1)*(i)/(i+j-2)*dp[i-1][j-2]it
2). 跳出的位黑色的。機率就是j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3]io
推到這裏基本上就出來了,剩下的邊界條件了。若是i==0,那麼機率必定是0, 若是i>0&&j==0那麼機率必定爲1.class
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1010; double dp[maxn][maxn]; double dfs(int i, int j) { if (i <= 0 || j < 0) return 0; if (i > 0 && j == 0) return dp[i][0] = 1; if (dp[i][j] != -1) return dp[i][j]; double t1 = (double)i / (i + j); double t2 = (double)j / (i + j); dp[i][j] = t1; if (i + j > 2) { double t3 = dfs(i, j - 3) * (j - 1) / (i + j - 1) * (j - 2) / (i + j - 2); double t4 = dfs(i - 1, j - 2) * (j - 1) / (i + j - 1) * (i) / (i + j - 2); t2 *= (t3 + t4); dp[i][j] = t1 + t2; } return dp[i][j]; } int main() { int w, b; scanf("%d%d", &w, &b); //memset(dp, -1, sizeof(dp)); for (int i = 0; i <= w; i++) for (int j = 0; j <= b; j++) dp[i][j] = -1; printf("%.9f\n", dfs(w, b)); return 0; }