卢克生日那天,汉来找卢克玩扑克牌,玩着玩着汉觉得太没意思了,于是决定给卢克一个考验
汉把一副扑克牌(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]即为所求

 #include<bits/stdc++.h>
using namespace std;
int A, B, C, D;
double f[][][][][][];
bool vis[][][][][][]; inline int read() {
int x = , y = ;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') y = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + ch - '';
ch = getchar();
}
return x * y;
} double Dp_to_make_ans(int a, int b, int c, int d, int p, int q) {
if(vis[a][b][c][d][p][q]) return f[a][b][c][d][p][q];
vis[a][b][c][d][p][q] = ;
int h = a, j = b, k = c, l = d;
if(p == ) h++; if(p == ) j++; if(p == ) k++; if(p == ) l++;
if(q == ) h++; if(q == ) j++; if(q == ) k++; if(q == ) l++;
if(h >= A && j >= B && k >= C && l >= D) return f[a][b][c][d][p][q] = ;
int sum = h + j + k + l;
double f_ans = ;
if(a < ) f_ans += Dp_to_make_ans(a + , b, c, d, p, q) * ( - a) / ( - sum);
if(b < ) f_ans += Dp_to_make_ans(a, b + , c, d, p, q) * ( - b) / ( - sum);
if(c < ) f_ans += Dp_to_make_ans(a, b, c + , d, p, q) * ( - c) / ( - sum);
if(d < ) f_ans += Dp_to_make_ans(a, b, c, d + , p, q) * ( - d) / ( - sum);
double shiki;
if(p == ) {
shiki = ;
for(int i = ; i <= ; ++i) shiki = min(shiki, Dp_to_make_ans(a, b, c, d, i, q));
f_ans = f_ans + shiki / ( - sum);
}
if(q == ) {
shiki = ;
for(int i = ; i <= ; ++i) shiki = min(shiki, Dp_to_make_ans(a, b, c, d, p, i));
f_ans = f_ans + shiki / ( - sum);
}
return f[a][b][c][d][p][q] = f_ans;
} int main() {
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
A = read(), B = read(), C = read(), D = read();
double ans = Dp_to_make_ans(, , , , , );
if(ans > ) ans = -;
printf("%0.3lf", ans);
return ;
}

TYVJ2002 扑克牌的更多相关文章

  1. SCNU 2015ACM新生赛初赛【1007. ZLM的扑克牌】解题报告

            题目链接详见SCNU 2015新生网络赛 1007. ZLM的扑克牌 .         其实我在想这题的时候,还想过要不要设置求最小的排列,并且对于回文数字的话,可以把扑克牌折起来( ...

  2. Java 用LinkdeList实现52张扑克牌

    用LinkdeList实现52张扑克牌(不含大小王)的洗牌功能.提示:花色 ,和数字分别用数组存储. import java.util.LinkedList; import java.util.Ran ...

  3. C算法编程题(一)扑克牌发牌

    前言 上周写<我的编程开始(C)>这篇文章的时候,说过有时间的话会写些算法编程的题目,可能是这两天周末过的太舒适了,忘记写了.下班了,还没回去,闲来无事就写下吧. 因为写C++的编程题和其 ...

  4. JAVA collection集合之 扑克牌游戏

    主要内容:这里使用collection集合,模拟香港电影中大佬们玩的扑克牌游戏. 1.游戏规则:两个玩家每人手中发两张牌,进行比较.比较每个玩家手中牌最大的点数,大小由A-2,点数大者获胜.如果点数相 ...

  5. Java程序设计之扑克牌

    这段代码的主要实现功能扑克牌的洗牌和发牌功能,一副牌,红桃,黑桃,梅花,方片,A~K,不含大小王. 构造一个class. 首先是声明花色: private String[] sign={"方 ...

  6. js运动框架之掉落的扑克牌(重心、弹起效果)

    玩过电脑自带纸牌游戏的同志们应该都知道,游戏过关后扑克牌会依次从上空掉落,落下后又弹起,直至"滚出"屏幕. 效果如图:    这个案例的具体效果就是:点击开始运动,纸牌会从右上角掉 ...

  7. javascript练习-扑克牌

    下面用枚举类型来实现一副扑克牌的类: //定义一个玩牌的类 function Card(suit,rank){ function inherit(p){ if(p==null) throw TypeE ...

  8. JavaScript学习笔记-实现枚举类型,扑克牌应用

    //实现枚举类型,扑克牌应用 function creatEnum(p){     //构造函数     var Enumeration = function(){throw 'can not Ins ...

  9. 华为OJ题目:扑克牌大小

    题目描述: 扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A.2各4张,小王1张,大王1张.牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):3  ...

随机推荐

  1. centos7.2编译安装zabbix-3.0.4

    安装zabbix-3.0.4 #安装必备的包 yum -y install gcc* make php php-gd php-mysql php-bcmath php-mbstring php-xml ...

  2. JDBC和Ibatis中的Date,Time,Timestamp处理

    在此前,遇到过使用Ibatis操作Oracle时时间精度丢失的问题,昨天又遇到JDBC操作MySQL时间字段的问题,从网上看到各种式样的解释这些问题的博文/帖子,但多是雾里看花,不得要领. 理解JDB ...

  3. codevs1066&&noip引水入城

    这道题 解决第一问 用灌水法 枚举第一行的每一个点 查找是否最后一行的每一个点是否都能灌到水 第二问 用反灌水发 枚举最后一行的每一个点 解决第一行每一个点所能覆盖的左右端点 可以证明每个点所能覆盖的 ...

  4. js中的document.ready

    1.概念 表示在dom结构绘制完成后执行,可能DOM元素关联的部分并未加载完 2.写法 $(document).on("ready",function(){ }) $(docume ...

  5. ThinkPHP5 正则验证中有“|”时提示“规则错误”的解决方案

    正则规则中有“|”时,会引起解析错误: 'regex:\d{3,4}[\s,-]?\d{7,8}|1[3,4,5,8]\d[\s,-]?\d{4}[\s,-]?\d{4}' 使用数组语法可以解决: [ ...

  6. (十六)strtok、strtok_s、strtok_r 字符串分割函数

    1.strtok函数 函数原型:char * strtok (char *str, const char * delimiters); 参数:str,待分割的字符串(c-string):delimit ...

  7. gradle问题总结与理解(一篇文章带你理解android studio 与gradle 的关系)

    前言:近日在网上找了个很不错的安卓二维码美化,由于下载的项目经常出问题,且不方便依赖使用,因此我想把它写个demo,并把源码发布到jcenter中,修改还是很顺利的,运行项目到手机也没问题,发布遇到了 ...

  8. golang相关问题

          [转载][翻译]Go的50坑:新Golang开发者要注意的陷阱.技巧和常见错误[1] Golang作为一个略古怪而新的语言,有自己一套特色和哲学.从其他语言转来的开发者在刚接触到的时候往往 ...

  9. 分割线用CSS样式做出来的效果

    一:单个标签实现分隔线:. ; ; line-height: 1px; border-left: 200px solid #ddd; border-right: 200px solid #ddd; t ...

  10. 初学jmeter

    jmeter安装的前提需要有jdk环境,下载安装好jdk环境后记得要设置好环境变量. 配置环境变量:右击“我的电脑”-->"高级"-->"环境变量" ...