码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-06-25 12:33:24      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:洗牌函数   概率   数组   算法   

题目描述:

写一个随机洗牌函数。要求洗出的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

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

标签:洗牌函数   概率   数组   算法   

原文地址:http://blog.csdn.net/tommyzht/article/details/46632845

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!