http://www.gdfzoj.com/oj/problem/470
桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。 输出答案时,小数点后第六位后的全部去掉,不要四舍五入.
令 f[i][j] 为 剩 i个红 j个黑时的期望
算期望 可以看出
f[i,j]:=f[i,j]+(i/(i+j)*(f[i-1,j]+1));
f[i,j]:=f[i,j]+(j/(i+j)*(f[i,j-1]-1));
i/(i+j) j/(i+j) 为概率
f[i-1,j]+1 f[i,j-1]-1为 所得效应
最后与 0 取 max 如小于 0 停止翻牌
最后 处理
f[r][b] -= 0.5;(向下取整)
f[r][b] = fabs(f[r][b]);(防止输出 -0.000000)
printf(“%.6lf\n”,f[r][b]);
下面是代码
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
double f[5050][5050];
int r,b,i,j,k,l,m,n;
int main(){
scanf("%d%d",&r,&b);
for(i=0;i<=r;i++)
for(j=0;j<=b;j++){
if (i) f[i][j] += (double)i/(double)(i+j)*(f[i-1][j]+1);
if (j) f[i][j] += (double)j/(double)(i+j)*(f[i][j-1]-1);
f[i][j]=max(0.0,f[i][j]);
}
f[r][b] -= 0.5;
f[r][b] = fabs(f[r][b]);
printf("%.6lf\n",f[r][b]);
return 0;
}
var i,j,k,l,m,n,q,w,r,b:longint;
f:array[0..5000,0..5000] of double;
t:double;
function max(p,o:double):double;
begin
if p>o then exit(p);exit(o);
end;
begin
readln(r,b);
for i:=0 to r do
for j:=0 to b do begin
if i>0 then f[i,j]:=f[i,j]+(i/(i+j)*(f[i-1,j]+1));
if j>0 then f[i,j]:=f[i,j]+(j/(i+j)*(f[i,j-1]-1));
f[i,j]:=max(f[i,j],0);
end;
t:=f[r,b];t:=t-0.5;t:=abs(t);
writeln(t:0:6);
end.