【BZOJ1419 Red is Good】裸数学期望DP
在队友做了一个半小时无果之后,怂得我不敢去做,,结果一下来,这不就是一个裸的数学期望DP嘛。。但是实际操作之后发现还是实现的很艰难,反复改了 很多次。(果然是我太弱了orz :) (好久没有做数学期望和概率了)
BZOJ传送门(权限题)
很显然这是一道裸的数学期望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:
问题描述
桌面上有 R 张红牌和 B 张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到 1 美元,黑牌则付出 1 美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。输入格式
一行输入两个数 R、B。输出格式
在最优策略下平均能得到多少钱。样例输入
5 1样例输出
4.166666数据规模和约定
R,B<=5000 输出答案时,小数点后第六位后的全部去掉,不要四舍五入。/* 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]); }