【bzoj1419】Red is good
问题描述
桌面上初始有NN张红牌,MM张黑牌,随机打乱顺序。之后我们一张一张地去翻牌,翻到红牌得到11幻想乡币,黑牌则付出11幻想乡币。可以随时停止翻牌。在最优策略下,我们得到的幻想乡币的数量期望是多少。
输入格式
一行两个非负整数,表示NN和MM。
输出格式
一个数表示答案。
样例输入
1 1
样例输出
0.5
提示
如果第一张是红牌,那直接停止游戏。收益为1,这种情况的概率是1/2。如果第一张是黑牌,继续翻下去,第二张一定是红牌。收益为0,这种情况的概率是1/2。与答案的差值≤10−5即视为正确。
【数据规模及约定】
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 }