博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TYVJ2002 扑克牌
阅读量:5908 次
发布时间:2019-06-19

本文共 3180 字,大约阅读时间需要 10 分钟。

卢克生日那天,汉来找卢克玩扑克牌,玩着玩着汉觉得太没意思了,于是决定给卢克一个考验

汉把一副扑克牌(54张)随机洗匀,倒扣着放成一摞。然后卢克从上往下一次翻开每张牌,每翻开一张黑桃,红桃,梅花或方块,就把它放到对应的花色的堆里去。
汉想问问卢克,得到A张黑桃,B张红桃,C张梅花,D张方块需要翻开的牌的张数的期望值E是多少
特殊的,如果翻开的牌是大小王,那么卢克可以把它作为某种花色的牌放入对应堆中。卢克会采取最优策略,使得放入之后E的值尽可能的小
显然卢克靠原力的感知可以无视这个问题,汉为给卢克丢了一个没意义的问题而懊恼,于是决定把问题丢给还是绝地学徒的你
虽然你并不能善用原力,但是好在你会c++,于是你可以靠程序解决这个问题。
卢克和汉还在玩牌,所以你可以在计算出结果后直接将答案汇报给他们
0<=A,B,C,D<=15 四舍五入保留三位小数输出

f[a,b,c,d,x,y]表示黑桃取了a张,红桃取了b张,梅花取了c张,方块取了d张,小王状态为x,大王状态为y时的期望值

具体来说,x = 4表示没有用过小王,x = 0~3表示用过小王,且把小王作为对应的花色(0代表黑桃,1代表红桃,2代表梅花,3代表方块)
可以知道的是,随着翻开的牌数的增加,得到某种花色的概率是在变化的。
当前已经翻开的牌总数sum = (a + b + c + d + (x == 4) + (y == 4))。到目前为止,还剩下54-sum张牌,其中13-a张黑桃,13-b张红桃,13-c张梅花,13-d张方块
以黑桃为例:
翻开一张黑桃的概率为(13 - a)/(54 - sum)。还需要翻开的牌的期望张数为f[a+1,b,c,d,x,y]。对于红桃,梅花,方块,情况类似
特别地,当x = 4时,有1/(54 - sum)的概率翻开小王。根据题意,应选择把小王看做某种花色,是期望值尽量小,即min{f[a,b,c,d,x',y]}(0<=x'<=3).对于大王,情况类似
对于大王,情况类似

方程显然且省略,建议直接看代码

初值:若已经翻开的牌数达到了题目要求的数量,则期望值位0.例如已经翻开的黑桃张数为a+(x==0)+(y==0),其余同理

目标f[0,0,0,0,4,4]

在数学期望递推,数学期望Dp中,通常把终止状态作为初值,把起始状作为目标状态,倒着进行计算。

原因:以本题为例:
根据数学期望的定义,若我们正着计算,则还需求出从起始状态到达每个终止状态的概率,与F值相乘求和才能得到答案,增加了难度,且易出错
而倒着计算,因为起始状态F[0,0,0,0,4,4]唯一,所以它的概率一定为1,最后直接输出f[0,0,0,0,4,4]即为所求

 

1 #include
2 using namespace std; 3 int A, B, C, D; 4 double f[15][15][15][15][5][5]; 5 bool vis[15][15][15][15][5][5]; 6 7 8 inline int read() { 9 int x = 0, y = 1;10 char ch = getchar();11 while(!isdigit(ch)) {12 if(ch == '-') y = -1;13 ch = getchar();14 }15 while(isdigit(ch)) {16 x = (x << 1) + (x << 3) + ch - '0';17 ch = getchar();18 }19 return x * y;20 }21 22 double Dp_to_make_ans(int a, int b, int c, int d, int p, int q) {23 if(vis[a][b][c][d][p][q]) return f[a][b][c][d][p][q];24 vis[a][b][c][d][p][q] = 1;25 int h = a, j = b, k = c, l = d;26 if(p == 0) h++; if(p == 1) j++; if(p == 2) k++; if(p == 3) l++;27 if(q == 0) h++; if(q == 1) j++; if(q == 2) k++; if(q == 3) l++;28 if(h >= A && j >= B && k >= C && l >= D) return f[a][b][c][d][p][q] = 0;29 int sum = h + j + k + l;30 double f_ans = 1;31 if(a < 13) f_ans += Dp_to_make_ans(a + 1, b, c, d, p, q) * (13 - a) / (54 - sum);32 if(b < 13) f_ans += Dp_to_make_ans(a, b + 1, c, d, p, q) * (13 - b) / (54 - sum);33 if(c < 13) f_ans += Dp_to_make_ans(a, b, c + 1, d, p, q) * (13 - c) / (54 - sum); 34 if(d < 13) f_ans += Dp_to_make_ans(a, b, c, d + 1, p, q) * (13 - d) / (54 - sum);35 double shiki;36 if(p == 4) {37 shiki = 100002;38 for(int i = 0; i <= 3; ++i) shiki = min(shiki, Dp_to_make_ans(a, b, c, d, i, q));39 f_ans = f_ans + shiki / (54 - sum);40 }41 if(q == 4) {42 shiki = 100002;43 for(int i = 0; i <= 3; ++i) shiki = min(shiki, Dp_to_make_ans(a, b, c, d, p, i));44 f_ans = f_ans + shiki / (54 - sum);45 }46 return f[a][b][c][d][p][q] = f_ans;47 }48 49 int main() {50 // freopen("test.in", "r", stdin);51 // freopen("test.out", "w", stdout);52 A = read(), B = read(), C = read(), D = read();53 double ans = Dp_to_make_ans(0, 0, 0, 0, 4, 4);54 if(ans > 54) ans = -1;55 printf("%0.3lf", ans);56 return 0;57 }

 

转载于:https://www.cnblogs.com/ywjblog/p/9692009.html

你可能感兴趣的文章
apache2.2 虚拟主机配置
查看>>
关于android:configChanges的属性
查看>>
iotop
查看>>
angular多个控制器如何共享数据
查看>>
Ogre Compositor解析
查看>>
SQLServer 2008以上误操作数据库恢复方法——日志尾部备份
查看>>
[转]强制取消TFS2008中其它成员的签出文件
查看>>
Dapper - .Net 环境下一个简单对象映射的框架
查看>>
CSS SANS – 神奇!使用 CSS3 创建的字体
查看>>
很好的理解遗传算法的样例
查看>>
Retrofit
查看>>
java设计模式1--工厂方法模式(Factory Method)
查看>>
一个Form中2个按钮,PHP后台如何判断提交的是哪一个按钮
查看>>
android 回车键事件编程
查看>>
CSS3 Media Queries模板
查看>>
Android调用系统关机与重启功能
查看>>
UDK游戏开发基础命令
查看>>
VisualSvn Server介绍
查看>>
ExtJs + Struts2 + JSON
查看>>
我为什么喜欢Go语言
查看>>