算法概要:
假设总金额为m,人数为n,每次分出的金额k
进行计算前,初始化了金额,使元变成了分,这样后面便于计算
每次分的金额是k为[1,2*m/n]之间的随机数,大部分抢红包程序都是按照这个比例算
当n>1并且m<n时,需要重新分配本次金额,保证每个人最少可以得到1分钱,
当n=1时,直接将剩下的金额全部分配出去
正常情况下,就直接分配k,并且m=m-k,n=n-1
具体算法实现如下:
public class Main {
public static void main(String[] args) {
//100元分随机20份
List<Double> list = initAmount(100,20);
double sum = 0d;
for (int i = 0; i < list.size(); i++) {
sum = sum + list.get(i);
System.out.println(list.get(i));
}
System.out.println(sum);
}
/**
* 初始化金额
* @param m 总金额
* @param n 分包数
* @return 每个包的金额
*/
public static List<Double> initAmount(Integer m, Integer n){
List<Double> list = new ArrayList<>();
Random random = new Random();
//金额乘100,使每个包精确到分,10元==1000分
getAmount(m*100,n,random,list,100);
return list;
}
/**
* 分配金额
* @param m 剩余金额
* @param n 分包数
* @param list 各包金额
* @param scale 精确额度
*/
public static void getAmount(Integer m, Integer n,Random random, List<Double> list,Integer scale){
//每次分到的金额,均值乘2
int a = random.nextInt(2*m/n)+1;
//如果人数大于1,并且剩余金额小于剩余人数,则重新计算本次分包金额,保证每个人最少能领到0.01元
if(n > 1 && m<n){
//重随机
getAmount(m,n,random,list,scale);
}else if(n==1){
list.add(BigDecimal.valueOf(m).divide(BigDecimal.valueOf(scale)).doubleValue());
m = 0;
}else{
m = m - a;
n = n - 1;
list.add(BigDecimal.valueOf(a).divide(BigDecimal.valueOf(scale)).doubleValue());
getAmount(m,n,random,list,scale);
}
}
}