Red is good

Time Limit: 10 Sec Memory Limit: 64 MB

Description

桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。

Input

一行输入两个数R,B。

Output

在最优策略下平均能得到多少钱。输出答案时,小数点后第六位后的全部去掉,不要四舍五入。

Sample Input

5 1

Sample Output

4.166666

HINT

R,B<=5000

Solution

这显然是一道简单的期望DP。我们令 f[i][j] 表示剩下 i 个红牌和 j 个黑牌时的最优答案。那么显然:

img

其中 i/(i+j) 和 j/(i+j) 表示选择到的概率。

最后由于卡内存,我们滚动一下数组即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
using namespace std;
typedef long long s64;

const int ONE = 5001;
const int E6 = 1e6;

int n,m;
double f[2][5001];

int get()
{
int res=1,Q=1; char c;
while( (c=getchar())<48 || c>57)
if(c=='-')Q=-1;
if(Q) res=c-48;
while((c=getchar())>=48 && c<=57)
res=res*10+c-48;
return res*Q;
}


int main()
{
n=get(); m=get();
for(int i=0,A=0; i<=n; i++,A^=1)
{
f[A][0] = i;
for(int j=0; j<=m; j++)
f[A][j] = max(0.0, (double)i/(i+j) * (f[A^1][j]+1) + (double)j/(i+j) * (f[A][j-1]-1) );
}
s64 record = floor(f[n&1][m] * E6);
printf("%lld.%06lld", record/E6, record%E6);
}