• [java,2018-06-26] 扑克牌抽牌求和问题


    问题:

    一副扑克牌,除去大小王后共52张牌,随机从中抽八张牌,问八张牌的和最有可能是多少?

    分析:

    这52张牌,其实就是数字 1 2 3 。。。13, 每个数字出现4次。随机抽出8个数,问组成的和最有可能是多少?

    很快想到了2种方法:

    1.根据 大数定理 ,多次模拟抽牌,求和,看和的分布情况

    2.在所有的C(52,8)种情况中,求出所有89(12-100)种情况和的组合数

    解法1:

    首先生成一副扑克牌,放入list中,每次随机取出一张牌后,list remove该元素,代码如下:

     1 package test;
     2 
     3 import java.util.ArrayList;
     4 import java.util.HashMap;
     5 import java.util.List;
     6 import java.util.Map;
     7 
     8 public class LargeNumbersTest {
     9     
    10     public static int getSum() {
    11         //生成一副扑克牌,放入list
    12         List<Integer> list=new ArrayList<Integer>();
    13         for(int i=1;i<14;i++){
    14             list.add(i);
    15             list.add(i);
    16             list.add(i);
    17             list.add(i);
    18         }
    19         
    20         int[] a=new int[8];
    21         for(int i=0;i<8;i++){
    22             int random=(int)(Math.random()*list.size());
    23             //随机取出一张牌,并在list集合中去除对应的数
    24             a[i]=list.get(random);
    25             list.remove(random);
    26         }
    27         int sum=0;
    28         for(int i=0;i<a.length;i++){
    29             sum+=a[i];
    30         }
    31         return sum;
    32     }
    33     public static void main(String[] args) {
    34         Map<Integer,Integer> map=new HashMap<Integer, Integer>();
    35         //多次重复试验
    36         for(int i=0;i<1000000;i++){
    37             int key=getSum();
    38             //试验结果存入map中,记录出现的次数
    39             if(map.keySet().contains(key)){
    40                 map.put(key, map.get(key)+1);
    41             }else{
    42                 map.put(key, 1);
    43             }
    44         }
    45         //输出map集合,本来想写一个按值排序的方法,搜了一下,太麻烦,果断放弃,改用excel处理结果
    46         for(Integer key:map.keySet()){
    47             System.out.println(map.get(key)+"	"+key);
    48         }
    49     }
    50 }

    运行5次后,输出结果在excel中排序,如下:

    可以看出,和是56的结果最多,大概39800,(只要三万九千八,求和结果带回家。。。),根据大数定理,估计和最可能的数是 56 ,概率约等于 0.0398,

    但是,和为57、55出现的次数也比较接近 56 ,是不是概率相等呢?

    我们求一下每种情况的准确概率(大数定理只能估算概率),请看解法2。

    解法2:

    模拟计算机抽牌的每一种情况,求出每一种情况下的和。

    1.如果按照每张牌的点数分类的话,每次抽牌都要考虑这张牌的点数 在本次抽牌中 出现的次数,太麻烦,所以对每张牌进行编号(0-51),

    问题转化为:在0-51中取出8个不同的数字,并对这8个数字代表的点数 求和。

    2.8个数字,8个变量,8次循环,感觉很low啊,不过我没想到好的办法,就先这样吧,希望大家找到好的办法能分享给我。

    代码如下:

     1 package test;
     2 
     3 import java.util.ArrayList;
     4 import java.util.HashMap;
     5 import java.util.List;
     6 import java.util.Map;
     7 
     8 public class PokerTest {
     9     public static void main(String[] args) {
    10         //生成一副扑克牌,放入list
    11         List<Integer> list=new ArrayList<Integer>();
    12         for(int i=1;i<14;i++){
    13             list.add(i);
    14             list.add(i);
    15             list.add(i);
    16             list.add(i);
    17         }
    18         int count=0;
    19         Map<Integer,Integer> map=new HashMap<Integer, Integer>();
    20         //模拟每一种抽牌结果,low到爆的8次循环
    21         for(int a1=0;a1<45;a1++){
    22             for(int a2=a1+1;a2<46;a2++){
    23                 for(int a3=a2+1;a3<47;a3++){
    24                     for(int a4=a3+1;a4<48;a4++){
    25                         for(int a5=a4+1;a5<49;a5++){
    26                             for(int a6=a5+1;a6<50;a6++){
    27                                 for(int a7=a6+1;a7<51;a7++){
    28                                     for(int a8=a7+1;a8<52;a8++){
    29                                         int sum=list.get(a1)+list.get(a2)
    30                                                 +list.get(a3)+list.get(a4)
    31                                                 +list.get(a5)+list.get(a6)
    32                                                 +list.get(a7)+list.get(a8);
    33                                         //记录抽牌总次数
    34                                         count++;
    35                                         //抽牌结果记录到map中,并记录次数
    36                                         if(map.keySet().contains(sum)){
    37                                             map.put(sum, map.get(sum)+1);
    38                                         }else{
    39                                             map.put(sum, 1);
    40                                         }
    41                                     }
    42                                 }
    43                             }
    44                         }
    45                     }
    46                 }
    47             }
    48         }
    49         for(Integer key:map.keySet()){
    50             System.out.println(map.get(key)+"	"+key);
    51         }
    52         System.out.println("count===="+count);
    53     }
    54     
    55 }

     结果依然是输出到excel中处理,

    首先  count====752538150  。。。。。超乎想象的大,看来解法一中的循环次数还是太少。

    用C(52,8)计算了下,这个结果没错

     概率计算结果

     

    得到和为 56 的概率为 0.039791 ,和解法1中估算的值 0.0398 比较接近了

    和为55、57的概率同为 0.039601 ,与和为 56 的概率差距真的很小了,

    就这样了

  • 相关阅读:
    [转]用mamcache 存储session的好处
    [转]怎么写 JQuery插件 (案例原理)
    关于查询优化
    HBase Canary
    HBase Bulk Loading
    有用的技术网站
    HBase 运维分析
    HBase rest
    hbase mlockall
    Jamon
  • 原文地址:https://www.cnblogs.com/shijt/p/9227878.html
Copyright © 2020-2023  润新知