• 写一个随机洗牌函数——概率题


    题目描写叙述:

    写一个随机洗牌函数。要求洗出的52!种组合都是等概率的。 也就是你洗出的一种组合的概率是1/(52!)。

    如果已经给你一个完美的随机数发生器。


    解题思路:

    这是一道概率题

    随机洗牌。目的是要做到随机性,要求每一张牌出现的概率要相等.

    我们经常使用的普通扑克牌54张,要做到每张牌出现的概率是1/(54!),

    抽第一张牌概率:1/54。

    抽第二张牌概率:1/53;

    抽第三张牌概率:1/52;

    ……

    一直这样随机地拿下去直到拿完最后1张,我们就从52!种可能中取出了一种排列。 这个排列相应的概率是1/(54!).

    这正是题目所要求的,随机洗牌目的.


    有了思路,接下来就是怎样编码实现。

    首先。我们有一个随机函数发生器,可以产生1-54之间的随机数,怎样保证抽第一张牌是54中可能,抽第二张牌是53中可能,……

    能够这样做。如果扑克牌是一个54维的数组card, 我们要做的就是从这个数组中随机取一个元素,然后在剩下的元素里再随机取一个元素… 这里涉及到一个问题。就是每次取完元素后,我们就不会让这个元素參与下一次的选取。 

    我们要实现的目的是以等概率的方式将这54个数随机打乱排列,因此,能够这样处理:

    第一次抽牌在初始54张牌中,将 随机产生的牌x,与第一个元素互换,

    第二次抽牌在剩下的53张牌中,将 随机产生的牌y,与第二个元素互换,

    ……

    举个样例,如果10张牌。arr[] = {1,2,3,4,5,6,7,8,9,10},假定第一次产生的牌是6。那么接下来的操作就是:将6与1互换,之后在剩下的{2,3,4,5,1,7,8,9,10}中产生第二个牌. ……


    參考代码:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    void Swap(int &a, int &b){// 有可能swap同一变量,不能用异或版本号
        int t = a;
        a = b;
        b = t;
    }
    
    void SwapXOR(int &a, int &b)//异或版本号的交换
    {
           a = a^b;
           b = a^b;
           a = a^b;
    }
    
    void RandomShuffle(int a[], int n){
        for(int i=0; i<n; ++i){
            int j = rand() % (n-i) + i;// 产生i到n-1间的随机数
            Swap(a[i], a[j]);//交换位置
        }
    }
    int main(){
        srand((unsigned)time(0));//随机种子
        int n = 54;
        int a[] = {
            1, 2, 3, 4, 5, 6, 7, 8, 9。10,……。54
        };
        RandomShuffle(a, n);//调用洗牌函数
        for(int i=0; i<n; ++i)//输出一次洗牌效果
            cout<<a[i]<<endl;
        return 0;
    }


    參考资料:

    1、http://www.cricode.com/2515.html

    2、http://coolshell.cn/articles/8593.html

  • 相关阅读:
    4.7字符串
    4.5 基本类型和运算符
    4.4 变量
    4.6 字符串
    hp
    openstack newton linuxbridge 改成 ovs
    理解裸机部署过程ironic
    csredis base usage
    redisclient can not connect
    Linux Install redis
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5079490.html
Copyright © 2020-2023  润新知