Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水題
阿新 • • 發佈:2017-11-14
emp down pro 表示 可能 problem %d 小兔 ||
給出w和b,求胡小兔贏的概率。
除非特別忙,我接下來會盡可能翻譯我做的每道CF題的題面!
Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水題
題面
胡小兔和司公子都認為對方是垃圾。
為了決出誰才是垃圾,大哥拿來了一袋老鼠,其中有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 水題