【bzoj1419】Red is good

问题描述

桌面上初始有NN张红牌,MM张黑牌,随机打乱顺序。之后我们一张一张地去翻牌,翻到红牌得到11幻想乡币,黑牌则付出11幻想乡币。可以随时停止翻牌。在最优策略下,我们得到的幻想乡币的数量期望是多少。

输入格式

一行两个非负整数,表示NN和MM。

输出格式

一个数表示答案。

样例输入

1 1

样例输出

0.5

提示

如果第一张是红牌,那直接停止游戏。收益为1,这种情况的概率是1/2。如果第一张是黑牌,继续翻下去,第二张一定是红牌。收益为0,这种情况的概率是1/2。与答案的差值105即视为正确。

【数据规模及约定】

30%的数据保证n,m≤10;

60%的数据保证n,m≤100;

100%的数据保证n,m≤1000。

题解

f[i][j]表示剩下i张红牌,j张黑牌的最大期望值,

f[i][j]=max(((f[i-1][j]+1)*i+(f[i][j-1]-1)*j)/(i+j),0)

如果当前翻的是红牌,收益为f[i-1][j]+1,概率为i/(i+j),期望为(f[i-1][j]+1)*i/(i+j)

如果当前翻的是黑牌,收益为(f[i][j-1]-1,概率为j/(i+j),期望为(f[i-1][j]+1)*j/(i+j)

总期望为(f[i-1][j]+1)*i/(i+j)+ (f[i-1][j]+1)*j/(i+j)

即((f[i-1][j]+1)*i+(f[i][j-1]-1)*j)/(i+j)

初始化 f[0][j]=0  f[i][0]=i

为什么要和零比较呢?

翻牌可以随时停止,那么最优策略就是保证期望非负。

即如果当前翻完牌后期望为负,那么显然不翻更优。

所以如果当前期望为负,就置为零。

 

 1 #include <cstdio>
 2 double f[1005][1005];
 3 int n,m;
 4 double max(double x,double y)
 5 {
 6     return x>y?x:y;
 7 }
 8 int main()
 9 {
10     int i,j;
11     scanf("%d%d",&n,&m);
12     for (i=1;i<=n;i++) f[i][0]=i*1.0;
13     for (i=1;i<=n;i++)
14       for (j=1;j<=m;j++)
15         f[i][j]=max(((f[i-1][j]+1)*i+(f[i][j-1]-1)*j)/(i+j),0.0);
16     printf("%.8f",f[n][m]);
17     return 0;
18 }

 

posted @ 2018-10-02 17:05  SAKURA12  阅读(260)  评论(0编辑  收藏  举报