实现抢红包算法

2020-04-04  本文已影响0人  492284513d5a

发出一个固定金额的红包,由若干人来抢,需要满足哪些规则?

1.所有人抢到金额之和等于红包金额,不能超过,也不能少于。
2.每个人至少抢到一分钱。
3.要保证所有人抢到金额的几率相等。

一般想到的是每次抢红包的时候直接随机就好,随机的上限是剩余的红包余额。
每次抢到的金额 = 随机区间(0,剩余金额)
但是这样是有问题的。先抢的人会有很大的优势,越往后的人随机的金额越小
例:
假设有10个人,红包总额100元。
第一个人的随机范围(0,100元),平均可以抢到50元。
假设第一人随机到50元,剩余金额是100-50 = 50元。
第二个人的随机范围是(0,50元),平均可以抢到25元。
以此类推,每一次随机范围越来越小。

二倍均值法

剩余红包金额为M,剩余人数为N,那么有如下公式:
每次抢到的金额 = 随机区间(0,M/N X 2)
这个公式 ,保证了每次随机金额的平均值是相等的,不会因为抢红包的先后顺序而造成不公平。
例:
假设有10个人,红包总额100元。
(100 / 20 )x 2 = 20 所以第一个人的随机范围是(0,20 ),平均可以抢到10元。
假设第一个人随机到10元,那么剩余金额是100-10 = 90 元。
90/9X2 = 20, 所以第二个人的随机范围同样是(0,20 ),平均可以抢到10元。
假设第二个人随机到10元,那么剩余金额是90-10 = 80 元。
80/8X2 = 20, 所以第三个人的随机范围同样是(0,20 ),平均可以抢到10元。
以此类推,每一次随机范围的均值是相等的。

import java.util.*;

public class WeiXinRedPackage1 {


public static void main(String[] args) {
    double sum = 0;
    ArrayList<Double> res 
           = WXRedPackageAlgorithm(10,3);

    for(double money:res) {
        sum += money;
        System.out.print(money +" ");
    }

    System.out.println();
    System.out.println(sum);     
}

private static ArrayList<Double> WXRedPackageAlgorithm(double restMoney,int restNum){                
    ArrayList<Double> res 
             = new ArrayList<>(restNum);

    Random random=new Random();
    while(restNum>1) {
        //最大的红包为:两倍的平均红包大小
        double max=(restMoney/restNum) * 2;

        //产生[0,1)之间的随机数
        double r=random.nextDouble();

        //抢到的红包区间[0,max)
        double money = r * max;
        if(money<0.01)
            money = 0.01;
        else 
            money= Math.floor(money*100)/100;        

        res.add(money);

        restNum--;
        restMoney -= money; 
    }   

    //最后一个红包为剩余余额
    res.add(Math.floor(restMoney*100)/100 );
    return res;
}
}
#!user/bin/env python
#-*- coding utf-8 -*-
# author:liruikun
import random
# summoney=input("please input the amount of money:")
# divide_n=input("divide into?:")

def hongbao(money,n):
    k=n
    sum=0#sum为前n个人抢得的总和,为了方便计算最后一个人的金额,初始值为0
    round=n#剩余人次
    while k>1:
        current_money = money  # 当前剩余的钱,初始值为money
        for i in range(1,n+1):
            get_money=random.randint(0,int(2*current_money/round))
            print('id[%s] have geted money %s'%(i,get_money))
            current_money -= get_money
            round -= 1
            sum += get_money
            k-=1


    if k==1:#最后一个人,分得剩余的所有
        print('id[%s] have geted money %s'%(n,money-sum))
    print(current_money)
hongbao(100,10)
上一篇下一篇

猜你喜欢

热点阅读