您的位置:首页 > 其它

LightOJ 1050 - Marbles(概率DP)

2015-11-25 23:25 399 查看
题意:红蓝两种球。你每次可随机拿一个,Jim每次只能拿蓝球。若Jim无球可拿,则他赢。若最后一个被拿的是蓝球,不管谁拿的都是你赢。否则Jim赢。求你赢的概率。

思路:dp[i][j]表示i个红球j个蓝球时你赢的概率。由于Jim悲催到只能拿蓝球,因此只有两个转移方向。则有

dp[i][j] = dp[i-1][j-1] * i / (i + j) + dp[i][j-2] * j / (i + j); (注意j >= 2时才加后面的 dp[i][j-2] * j / (i + j))

我们注意到,当i > j时,显然你不管怎么搞都是赢不了的。首先为了不让Jim赢,你得保证结束前他有球可拿,所以你不能跟着他一起拿蓝球,这样你就只能拿红的。那么显然当该你拿球且红球比蓝球多时,你不管怎么搞在结束前Jim一定会把蓝球拿完导致之后他没球拿,所以dp[i][j] = 0(i > j)。

根据题意显然有,dp[0][i] = 1.0 (i >= 0), dp[i][0] = 0(i >= 1)。

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;

typedef long long LL;
#define mem(a, n) memset(a, n, sizeof(a))
#define ALL(v) v.begin(), v.end()
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define pb push_back
#define eps 1e-8
const int inf = 0x3f3f3f3f, N = 5e2 + 5, MOD = 1e9 + 7;

int T, cas = 0;
int n, m;
int R, B;
double dp

;

void init() {
mem(dp, 0);
dp[0][0] = 1.0;
for(int i = 1; i <= 500; i ++) {
dp[i][0] = 0.0;
dp[0][i] = 1.0;
}
for(int i = 1; i <= 500; i ++) {
for(int j = 1; j <= 500; j ++) {
if(i > j) dp[i][j] = 0.0;
else {
dp[i][j] = dp[i-1][j-1] * i * 1.0 / (i + j);
if(j - 2 >= 0) dp[i][j] += dp[i][j-2] * j * 1.0 / (i + j);
}
}
}
}

int main(){
#ifdef LOCAL
freopen("/Users/apple/input.txt", "r", stdin);
//	freopen("/Users/apple/out.txt", "w", stdout);
#endif

init();
si(T);
while(T --) {
sii(R, B);
printf("Case %d: %.10f\n", ++ cas, dp[R][B]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: