**
*
*/
public class Demo10 {
/*
* 1.红包总结不超过200*100,单位(分)
* 2.每个红包都要有钱,最低不能低于1分
*/
private static final int MINMONEY=1;
private static final int MAXMONEY=200*100;
/*
* 为了避免某个红包占用大量金额,需要设定非最后一个红包的最大金额,设置为
* 红包金额的N倍
*/
private static final double TIMES=2.1;
/**
* 拆分红包
* @param money:红包总金额
* @param count:个数
* @return
*/
public List<Integer> splitRedPackets(int money,int count){
//校验红包的合法性
if(!isRight(money,count)){
return null;
}
//红包列表
List<Integer> list = new ArrayList<Integer>();
//每个红包最大的金额为平均金额的Times倍
int max = (int) (money*TIMES/count);
max = max>MAXMONEY?MAXMONEY:max;
//分配红包
for (int i = 0; i < count; i++) {
int one = randomRedPacket(money,MINMONEY,max,count-1);
list.add(one);
money-=one;
}
return list;
}
private int randomRedPacket(int money, int minS, int maxS, int count) {
//若是只有一个红包,直接返回
if(count==1){
return maxS;
}
//若是最小金额红包==最大金额红包,直接返回最小金额红包
if(minS==maxS){
return minS;
}
//校验最大值max要是比money的金额多的话,去money的金额
int max = maxS>money?money:maxS;
//随机一个红包=随机一个数*(金额-最小)+最小
int one =((int)Math.rint(Math.random()*(max-minS)+minS));
//剩下的金额
int moneyOther = money-one;
//校验这种随机方案是否可行,不合法的话,就要重新分配方案
if(!isRight(moneyOther,count-1)){
return one;
}else{
//重新分配
double avg = moneyOther/(count-1);
//本次红包过大,导致下次的红包过小;如果红包过大,
//下次就随机一个小值到本次红包金额的一个红包
if(avg<MINMONEY){
//递归调用,修改红包最大金额;
return randomRedPacket(money,one,maxS,count);
}else if(avg>MAXMONEY){
return randomRedPacket(money,one,maxS,count);
}
}
return one;
}
private boolean isRight(int money, int count) {
double avg = money/count;
//小于最小金额
if(avg<MINMONEY){
return false;
}else if(avg>MAXMONEY){
return false;
}
return true;
}
public static void main(String[] args) {
Demo10 dd = new Demo10();
System.out.println(dd.splitRedPackets(120,6));
}
}
* Java模拟微信红包分配算法(还有点问题,明天优化一下)
* @author Administrator*
*/
public class Demo10 {
/*
* 1.红包总结不超过200*100,单位(分)
* 2.每个红包都要有钱,最低不能低于1分
*/
private static final int MINMONEY=1;
private static final int MAXMONEY=200*100;
/*
* 为了避免某个红包占用大量金额,需要设定非最后一个红包的最大金额,设置为
* 红包金额的N倍
*/
private static final double TIMES=2.1;
/**
* 拆分红包
* @param money:红包总金额
* @param count:个数
* @return
*/
public List<Integer> splitRedPackets(int money,int count){
//校验红包的合法性
if(!isRight(money,count)){
return null;
}
//红包列表
List<Integer> list = new ArrayList<Integer>();
//每个红包最大的金额为平均金额的Times倍
int max = (int) (money*TIMES/count);
max = max>MAXMONEY?MAXMONEY:max;
//分配红包
for (int i = 0; i < count; i++) {
int one = randomRedPacket(money,MINMONEY,max,count-1);
list.add(one);
money-=one;
}
return list;
}
private int randomRedPacket(int money, int minS, int maxS, int count) {
//若是只有一个红包,直接返回
if(count==1){
return maxS;
}
//若是最小金额红包==最大金额红包,直接返回最小金额红包
if(minS==maxS){
return minS;
}
//校验最大值max要是比money的金额多的话,去money的金额
int max = maxS>money?money:maxS;
//随机一个红包=随机一个数*(金额-最小)+最小
int one =((int)Math.rint(Math.random()*(max-minS)+minS));
//剩下的金额
int moneyOther = money-one;
//校验这种随机方案是否可行,不合法的话,就要重新分配方案
if(!isRight(moneyOther,count-1)){
return one;
}else{
//重新分配
double avg = moneyOther/(count-1);
//本次红包过大,导致下次的红包过小;如果红包过大,
//下次就随机一个小值到本次红包金额的一个红包
if(avg<MINMONEY){
//递归调用,修改红包最大金额;
return randomRedPacket(money,one,maxS,count);
}else if(avg>MAXMONEY){
return randomRedPacket(money,one,maxS,count);
}
}
return one;
}
private boolean isRight(int money, int count) {
double avg = money/count;
//小于最小金额
if(avg<MINMONEY){
return false;
}else if(avg>MAXMONEY){
return false;
}
return true;
}
public static void main(String[] args) {
Demo10 dd = new Demo10();
System.out.println(dd.splitRedPackets(120,6));
}
}