【BZOJ1419 Red is Good】裸数学期望DP

在队友做了一个半小时无果之后,怂得我不敢去做,,结果一下来,这不就是一个裸的数学期望DP嘛。。但是实际操作之后发现还是实现的很艰难,反复改了 很多次。(果然是我太弱了orz :) (好久没有做数学期望和概率了) BZOJ传送门(权限题)

问题描述

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

输入格式

一行输入两个数 R、B。

输出格式

在最优策略下平均能得到多少钱。

样例输入

5 1

样例输出

4.166666

数据规模和约定

R,B<=5000 输出答案时,小数点后第六位后的全部去掉,不要四舍五入。  
很显然这是一道裸的数学期望dp。设定状态 f[i][j]表示目前还剩i张红牌,j张黑牌的情况下的期望得分。 由于随时可以停止,所以我们可以想到,当f[i][j]<0时我们可以强行将其归0. 于是我们就得到了DP方程:f[i][j] = max( 0 , (f[i-1][j]+1) * i/(i+j) + (f[i][j-1]-1)*j/(i+j)。 然后看数组大小,滚动数组罢。 剩下的也没什么好说的了,直接 上code:
/*
f[i][j]表示剩余i张red,j张black可以获得的最大数学期望
f[i][j] = max( 0 , (f[i-1][j]+1)*(i)/(i+j) + (f[i][j-1]-1)*(j)/(i+j) ) 
*/
#include<bits/stdc++.h>
using namespace std;
int  r,b;
double f[2][5005];
int main()
{
	scanf("%d%d",&r,&b);
	for(int i=1;i<=r;i++)
	{
		f[i&1][0] = i*1.0;
		for(int j=1;j<=b;j++)
		{
			f[i&1][j] = max(0.0,1.0*(f[(i&1)^1][j]+1.0)*(1.0*i/(1.0*(i+j))) + (f[i&1][j-1]-1)*(1.0*j/(1.0*(i+j))) );
		}
	}
	printf("%.6f",f[r&1][b]);
}
   
posted @ 2018-05-23 00:18  Newuser233  阅读(8)  评论(0)    收藏  举报