zoukankan      html  css  js  c++  java
  • 0x30数学知识(0x38 概率与数学期望)例题3:扑克牌(题解)

    题意

    题目链接

    【题意】
    Admin生日那天,Rainbow来找Admin玩扑克牌。
     玩着玩着Rainbow觉得太没意思了,于是决定给Admin一个考验。
    Rainbow把一副扑克牌(54张)随机洗开,倒扣着放成一摞。
     然后Admin从上往下依次翻开每张牌,每翻开一张黑桃、红桃、梅花或者方块,就把它放到对应花色的堆里去。
    Rainbow想问问Admin,得到A张黑桃、B张红桃、C张梅花、D张方块需要翻开的牌的张数的期望值E是多少?
     特殊地,如果翻开的牌是大王或者小王,Admin将会把它作为某种花色的牌放入对应堆中,使得放入之后E的值尽可能小。
     由于Admin和Rainbow还在玩扑克,所以这个程序就交给你来写了。
    
     【输入格式】
     输入仅由一行,包含四个用空格隔开的整数,A,B,C,D。
    
     【输出格式】
     输出需要翻开的牌数的期望值E,四舍五入保留3位小数。
     如果不可能达到输入的状态,输出-1.000。
    
     【数据范围】
    0≤A,B,C,D≤15
    
    【输入样例】
    1 2 3 4
    
    【输出样例】
    16.393
    

    题解

    这道题目乍一看特别难,一看入门,我佛了,被入门题吊着打。

    看了题解才会。

    (f[a][b][c][d][q][p]),当(q==0,p==0)时,这个表示的是期望拿几张牌能使得目前的牌堆满足要求。

    那么(q)表示的就是小王了,当他等于(0),表示没找到,当他等于(1~4)时,分别表示化作什么花色。

    (p)同理。

    然后DP方程(sum表示拿的牌数):

    在这里插入图片描述
    方程来自:https://blog.csdn.net/Ronaldo7_ZYB/article/details/89526291

    当然这坨式子这么长,当然用记忆化搜索是最简单实现的啦。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define  N  20
    using  namespace  std;
    double  dp[N][N][N][N][6][6];
    inline  double  mymin(double  x,double  y){return  x<y?x:y;}
    int  a,b,c,d;
    double  dfs(int  a1,int  a2,int  a3,int  a4,int  q,int  p)
    {
    	if(dp[a1][a2][a3][a4][q][p]>1e-8)return  dp[a1][a2][a3][a4][q][p];
    	if(a1+(q==1)+(p==1)>=a  &&  a2+(q==2)+(p==2)>=b  &&  a3+(q==3)+(p==3)>=c  &&  a4+(q==4)+(p==4)>=d)return  0;
    	int  cnt=a1+a2+a3+a4+(q!=0)+(p!=0);
    	dp[a1][a2][a3][a4][q][p]=1.0;//把所有的概率加在一起得到的这个1
    	if(a1<13)dp[a1][a2][a3][a4][q][p]+=dfs(a1+1,a2,a3,a4,q,p)*(13-a1)/(54-cnt);
    	if(a2<13)dp[a1][a2][a3][a4][q][p]+=dfs(a1,a2+1,a3,a4,q,p)*(13-a2)/(54-cnt);
    	if(a3<13)dp[a1][a2][a3][a4][q][p]+=dfs(a1,a2,a3+1,a4,q,p)*(13-a3)/(54-cnt);
    	if(a4<13)dp[a1][a2][a3][a4][q][p]+=dfs(a1,a2,a3,a4+1,q,p)*(13-a4)/(54-cnt);
    	if(q==0)dp[a1][a2][a3][a4][q][p]+=mymin(mymin(dfs(a1,a2,a3,a4,1,p),dfs(a1,a2,a3,a4,2,p)),mymin(dfs(a1,a2,a3,a4,3,p),dfs(a1,a2,a3,a4,4,p)))/(54-cnt);
    	if(p==0)dp[a1][a2][a3][a4][q][p]+=mymin(mymin(dfs(a1,a2,a3,a4,q,1),dfs(a1,a2,a3,a4,q,2)),mymin(dfs(a1,a2,a3,a4,q,3),dfs(a1,a2,a3,a4,q,4)))/(54-cnt);
    	return  dp[a1][a2][a3][a4][q][p];
    }
    int  main()
    {
    	scanf("%d%d%d%d",&a,&b,&c,&d);
    	if (max(a-13,0)+max(b-13,0)+max(c-13,0)+max(d-13,0)>2){printf("-1.000
    ");return  0;}//无解判断
    	double  ans=dfs(0,0,0,0,0,0);
    	printf("%.3lf
    ",ans);
    	return  0;
    }
    
  • 相关阅读:
    [原创]手把手教你如何把二维码插件zxing加入到android和ios项目中
    解决通过Intent调用系统拍照程序,返回图片太小的问题[android] 【转】
    SVN Command
    取得ie 里面 自定义函数或者属性的集合 使用RuntimeObject()
    scrum 开发模型
    javascript AOP 实现,ajax回调函数使用比较方便
    印度英语的特点
    AspectJS
    java 打jar包 转
    XP 开发模式
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/11716448.html
Copyright © 2011-2022 走看看