bzoj1419--Red is Good--期望dp

问题描述

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

输入格式

  一行输入两个数 R、B。

输出格式

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

样例输入

  5 1

样例输出

  4.166666

数据规模和约定

  R,B<=5000

  输出答案时,小数点后第六位后的全部去掉,不要四舍五入。

题解:

  今天的考题,顺便贴一波题解……我们定义f(i,j)为当前状态下,还有i张红牌和j张黑牌没翻的期望受益,转移时两种情况下的结果都要考虑。

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

  空间注意要用滚动数组。

 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #define ans1 ((f[j-1][end]+1)*j/i)
 7 #define ans2 ((f[j][end]-1)*(i-j)/i)
 8 #define ll long long
 9 using namespace std;
10 //const int maxn=5001;
11 inline void Edwina()
12 {
13     freopen("red.in","r",stdin);
14     freopen("red.out","w",stdout);
15 }
16 double f[10009][2];//开滚动数组 
17 double mmax(double a,double b){return a>b?a:b;}
18 int main()
19 {
20     Edwina();
21     int R,B,k=0,end=1;
22     scanf("%d%d",&R,&B);
23     for(int i=1;i<=R+B;i++,end^=1,k^=1)
24     {
25         for(int j=0;j<=i&&j<=R;j++)
26         {
27             if(j==0)
28                 f[j][k]=0;
29             else
30             {
31                 if(i==j)
32                     f[j][k]=j;
33                 else
34                     f[j][k]=mmax(0,ans1+ans2);
35                     //ans1 ((f[j-1][end]+1)*j/i)
36                     //ans2 ((f[j][end]-1)*(i-j)/i)
37             }
38         }
39     }
40     printf("%.6lf\n",floor(f[R][end]*1000000)/1000000);//对于小数位的处理 
41     //ll ans=(ll)(f[R][end]*1000000);
42     //printf("%lld.%06lld\n",ans/1000000,ans%1000000);
43     fclose(stdin);
44     fclose(stdout);
45     return 0;
46 }
View Code

 

posted @ 2017-08-20 21:45  BK-Edwina  阅读(246)  评论(0编辑  收藏  举报