1. 程式人生 > >Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水題

Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水題

emp down pro 表示 可能 problem %d 小兔 ||

除非特別忙,我接下來會盡可能翻譯我做的每道CF題的題面!

Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水題

題面

胡小兔和司公子都認為對方是垃圾。
為了決出誰才是垃圾,大哥拿來了一袋老鼠,其中有w只白老鼠和b只黑老鼠。胡小兔先抓,先抓到白老鼠的人贏。
每次學姐抓完老鼠之後,總會有另外一只老鼠從袋子裏自己跑出來(這只老鼠不算任何人抓的),而胡小兔抓老鼠時則不會發生這樣的事。
每次袋子裏的每只老鼠被抓到的概率相等,當有一只老鼠跑出來的時候,每只老鼠跑出來的幾率也相等。抓出來和跑出來的老鼠都不會回到袋子中。
如果袋子裏沒有老鼠了,並且沒有人抓到過白老鼠,則學姐贏。

給出w和b,求胡小兔贏的概率。

數據範圍:w, b <= 1000。


題解

這道題還是很水的,dp[i][j][0/1]表示“還剩i黑j白,該胡小兔/學姐抓,胡小兔贏的概率”。寫出轉移方程即可:

$ dp[i][j][0] = \frac{i}{i + j} dp[i - 1][j][1] + \frac{j}{i + j} $
$ dp[i][j][1] = \frac{i}{i + j} * \frac{i - 1}{i + j - 1} dp[i - 2][j] + \frac{i}{i + j} * \frac{j}{i + j - 1} dp[i - 1][j - 1] $ (前面是抓黑跑黑,後面是抓黑跑白)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
bool read(T &x){
    char c;
    bool
op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; else if(c == EOF) return 0; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; return 1; } template <class T> void write(T x){ if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 1003; int w, b; double dp[N][N][2]; int main(){ read(w), read(b); for(int i = 0; i <= b; i++) for(int j = 0; j <= w; j++){ if(i + j) dp[i][j][0] += (double)j / (i + j); if(i) dp[i][j][0] += (double)i / (i + j) * dp[i - 1][j][1]; if(i > 1) dp[i][j][1] += (double)i / (i + j) * (i - 1) / (i + j - 1) * dp[i - 2][j][0]; if(i && j) dp[i][j][1] += (double) i / (i + j) * j / (i + j - 1) * dp[i - 1][j - 1][0]; //printf("dp[%d][%d][0] = %lf, dp[%d][%d][1] = %lf\n", i, j, dp[i][j][0], i, j, dp[i][j][1]); } printf("%.11lf\n", dp[b][w][0]); return 0; }

Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水題