100的红包7个人随机分,限制值在10-30之间

本文介绍了一种红包金额随机分配的算法实现,通过两种不同的策略确保红包金额在设定的范围内公平随机地分配给指定数量的接收者,同时保持总额不变。
public class RedPacketTest {

    public static void main(String[] args) {

        for (int i = 0; i < 5; i++) {
            splitRedPacket(100.00, 7, 10.0, 30.0);

        }
    }


    /**
     * 每个数由最小值加上随机数,每次生成随机数由剩余的数减去随机数
     *
     * @param total      总和
     * @param splitCount 分割的个数
     * @param min        最小值
     * @param max        最大值
     */
    public static void splitRedPacket1(Double total, int splitCount, Double min, Double max) {
        Double left = Double.parseDouble("" + (total - splitCount * min));
        Random random = new Random();
        DecimalFormat dcmFmt = new DecimalFormat("0.00");
        Double num;
        ArrayList<Double> list = new ArrayList<>();
        do {
            num = random.nextFloat() * left;
            if (num < max - min && num > 0) {
                //在差值之间
                splitCount--;
                if (splitCount == 0) {
                    num = left;
                }
                list.add(Double.parseDouble(dcmFmt.format(num + min)));
                left = Double.parseDouble(dcmFmt.format(left - num));
            }
        } while (splitCount != 0);

        //随机排序
        Collections.shuffle(list);

        System.out.println(Arrays.toString(list.toArray()));

        Double sum = 0.0;
        for (double x : list) {
            sum = sum + x;
        }
        System.out.println("验证总和:" + dcmFmt.format(sum));
    }


    /**
     * 判断个数奇偶,奇数先生成一个,剩下的配对,求出各队的总和,先随机生成一个,后由总数减去随机数
     *
     * @param total
     * @param splitCount
     * @param min
     * @param max
     */
    public static void splitRedPacket(Double total, int splitCount, Double min, Double max) {

        ArrayList<Double> al = new ArrayList<>();
        Random random = new Random();
        DecimalFormat dcmFmt = new DecimalFormat("0.00");

        // 奇数个红包,需要单独将其中一个红包先生成,以保证后续算法拆分份数为偶数。
        if ((splitCount & 1) == 1) {
            Double num = 0.0;
            do {
                num = random.nextDouble() * max;
            } while (num >= max || num <= min);

            total = Double.parseDouble(dcmFmt.format(total - num));
            al.add(Double.parseDouble(dcmFmt.format(num)));
        }
        int couples = splitCount >> 1;
        Double perCoupleSum = total / couples;
        perCoupleSum = Double.parseDouble(dcmFmt.format(perCoupleSum));

        for (int i = 0; i < couples; i++) {
            Double num1 = 0.0;
            Double num2 = 0.0;
            do {
                num1 = random.nextDouble() * max;
                num2 = Double.parseDouble(dcmFmt.format(perCoupleSum - num1));
                if (!al.contains(num1) && !al.contains(num2)) {
                    if (i == 0) {
                        num1 = (total - couples * perCoupleSum) + num1;
                    }
                }
            } while (num1 < min || num1 > max || num2 < min || num2 > max);
            al.add(Double.parseDouble(dcmFmt.format(num1)));
            al.add(Double.parseDouble(dcmFmt.format(num2)));
        }
        System.out.println("------------" + Arrays.toString(al.toArray()));

        Double check_num = 0.0;
        for (Double x : al) {
            check_num = check_num + x;
        }
        System.out.println("验证总和:" + dcmFmt.format(check_num));
    }

}

 

任务描述 本关任务:编写一个将红包金额按一定数量随机配的小程序。 问题析 既然要模拟抢红包,那么我们需要解决以下问题: 抢到的红包金额是看运气的,所以一定需要公平; 红包金额最大不能超过 200 元,每个人到的红包最小不能少于 1 钱,红包的最小单位是; 我们需要避免前面配的红包比重过大,导致后面的红包过小。 实现流程 红包金额限制:我们先定义两个常量,用于设置红包的最大额度与最小额度,单位这里我们统一用; 判断红包金额是否合法(即红包最大金额不得超过 200,最小金额不得小于 0.1): 在红包之前判断红包总金额以及每个人领到的红包金额是否合法; 在红包之后判断剩下的人领到的红包金额是否合法。 为了避免红包配过大,我们需要设置每个包最大值为剩余红包平均数(剩余红包金额 / 剩余红包数量)的 2 倍,红包最小值依然为 0.1 ,当设置的每个包的最大值大于剩余红包总金额时,此时每个包的最大值为红包总金额; 开始红包时,如果剩余红包数量为 1,则直接返回剩余红包总金额; 如果红包数量不为 1,则我们在每个包的最大值与最小值之间随机产生一个整数,这里我们的产生随机数的算法公式为: ((int)Math.rint(Math.random() * (每个包的最大值 - 每个包的最小值) + 每个包的最小值)) % 每个包的最大值 + 1; 在红包之后判断剩下的人领到的红包金额是否合法,如果不合法,我们需要重新产生配方案,在重新产生配方案的时候,我们需要确定一个事情,是产生的红包过大还是过小,如果红包过大,下次就随机一个最小值到本次红包金额之间的一个红包,如果红包金额过小,我们就产生一个此次红包金额到最大值之间的一个红包; 依次执行,最后将配到的红包金额放入一个 List 集合中。 编程要求 仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 中完成随机红包的功能,具体要求如下: RedPacketUtil 类定义了一个 splitRedPackets(int money, int count) 的方法,方法返回值为 List 集合,传入的两个参数别为红包总金额(单位:)和红包数量,将配好的红包放入 List 集合,最后将该集合返回; 如果初始金额大于 200 元和每个包的值小于 1 ,输出:“红包金额不合法”,之后退出程序。 测试说明 平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。 可在右侧“测试结果”区查看具体的测试集详情。 测试输入: 100 10 第一次输入的值为红包总金额:100 ; 第二次输入的值为红包数量:10 ; 预期输出: [2, 17, 6, 9, 3, 8, 18, 18, 2, 17] 红包发送成功 开始你的任务吧,祝你成功! 下面是题目框架import java.util.ArrayList; import java.util.List; public class RedPacketUtil { // 请在下面的Begin-End之间编写正确的代码 /********** Begin **********/ // 最小红包额度 // 最大红包额度 // 每个红包最大是平均值的倍数 /** * 参数 money * 参数 count * 返回值 List * 功能: 拆红包 */ public List<Integer> splitRedPackets(int money, int count) { } /** * 参数 money * 参数 minS 最小值 * 参数 maxS 最大值 * 返回值 int * 功能 获取每个包的随机金额 */ private int random(int money, int minS, int maxS, int count) { } /********** End **********/ }
06-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值