• 红包计算的方法(通过2倍指数法进行计算,通过线性切割法计算)


    方法一:

    1.方法可灵活对不同数量的人随机产生点开的红包金额

    2.采取2倍指数法计算每个人的红包(2倍指数法:根据人数计算平均红包值,将该数放大两倍即随机红包范围,最后一个拿剩下的所有)

    3.红包精确到分

    4.应确保每个人至少能拿到1分钱的红包

    public class RedMoney {
        /**
         * 将金额四舍五入
         * @param cash
         * @return
         */
        public double round(double cash){
            BigDecimal bd=new BigDecimal(cash);
            //CigDecimal是类,不能直接用于计算,所以要获取他的value值
            return bd.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        /**
         * 获取红包金额的方法
         * @param count
         * @param money
         */
        public void red(int count,double money){
            //目前每个人分到的总金额
            double total=0;
            for(int i=0;i<=count;i++){
                //每个人分到的红包金额
                double cash;
                //要先判断是不是最后一个人,如果是最后一个人则拿到剩下的所以红包
                if(i==count-1){
                    cash=round(money);
                    System.out.println("最后一个红包金额是:"+cash);
                    //计算每个人领的红包总金额
                    total+=cash;
                    break;
                }
                //利用二倍指数法获取每个人抽取红包金额的随机范围
                //剩余总金额在变,人数也在变
                double avg=round(money/(count-i));
                double range=avg*2;
                cash=round(Math.random()*range);
                //如果这次抽到的小于0.01,则此次不算,跳过重新抽一次
                if(cash<0.01){
                    i--;
                    continue;
                }
                System.out.println("第"+i+"个人抽到的红包:"+cash);
                //计算剩余总金额
                money-=cash;
                //将剩余总金额保留两位
                money=round(money);
                //目前累计已经抽到的红包总金额
                total+=cash;
            }
            System.out.println("抽取红包的总金额:"+total);
        }
    
        /**
         * 调用红包生成的方法
         * @param args
         */
        public static void main(String[] args) {
            RedMoney redMoney=new RedMoney();
            redMoney.red(20, 10);
        }
    }

    方法二:

    使用线性分割的方法进行红包计算(在红包总金额的范围内生成红包切割点)

    public class RedMoney {
    
        /**
         * 获取红包金额的方法
         * @param count
         * @param money
         */
        public void red(int count,int money){
            double total=0;
            //根据人数创建切割垫
            double[] array=new double[count-1];
            for(int i=0;i<array.length;i++){
                //剩余总金额在变,所以切割点范围在变
                double point=round(Math.random()*money);
                //判断数组中是否已经存在
                if(hasSameElement(array,point)){
                    i--;
                    continue;
                }
                //判断生成的值是否小于0.01
                if(point<0.01){
                    i--;
                    continue;
                }
                //将符合条件的切割点添加至切割点数组
                array[i]=point;
            }
            //对红包切割点进行排序
            sort(array);
            //如果是第一个红包
            for(int i=1;i<count;i++){
                double cash;
                if(i==1){
                    cash=array[0];
                }
                else if(i==count){
                    cash=money-array[array.length-1];
                }
                else{
                    cash=array[i-1]-array[i-2];
                }
                cash=round(cash);
                total+=cash;
                System.out.println("第"+i+"个人分到的红包金额是"+cash);
            }
            System.out.println("总金额"+total);
        }
    
    
        /**
         * 将金额四舍五入
         * @param cash
         * @return
         */
        public double round(double cash){
            BigDecimal bd=new BigDecimal(cash);
            //CigDecimal是类,不能直接用于计算,所以要获取他的value值
            return bd.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
        }
    
    
        /**
         * 判断数组中是否已经存在该分割点
         * @param array
         * @param value
         * @return
         */
        public boolean hasSameElement(double[] array,double value){
            boolean flag=false;
            //遍历数组
            for(int i=0;i<array.length;i++){
                //判断数组中是否有重复
                if(array[i]==value){
                    //如果有则修改标识
                    flag=true;
                    break;
                }
            }
            return flag;
        }
    
        /**
         * 冒泡排序法,将红包截点进行排序
         * @param array
         */
        public void sort(double[] array){
            for(int i=1;i<array.length;i++){
                for(int j=0;j<array.length-i;j++){
                    if(array[j]>array[j+1]){
                        double temp =array[j];
                        array[j]=array[j+1];
                        array[j+1]=temp;
                    }
                }
            }
        }
        
        /**
         * 调用红包生成的方法
         * @param args
         */
        public static void main(String[] args) {
            RedMoney redMoney=new RedMoney();
            redMoney.red(10,10);
        }
    }
  • 相关阅读:
    2019牛客暑期多校训练营(第八场)A All-one Matrices(单调栈+前缀和)
    2019牛客暑期多校训练营(第三场)A Graph Games(分块)
    2019牛客暑期多校训练营(第二场)E MAZE(线段树维护矩阵+DP)
    2019牛客暑期多校训练营(第二场)D Kth Minimum Clique(bitset+暴力枚举)
    2019牛客暑期多校训练营(第一场)H XOR(线性基)
    2019牛客暑期多校训练营(第六场)D Move(multiset+枚举)
    2019牛客暑期多校训练营(第五场)H subsequence 2(拓扑排序)
    2019牛客暑期多校训练营(第六场)J Upgrading Technology(矩阵前缀和+最小子串和+贪心)
    2019牛客暑期多校训练营(第五场)G subsequence 1(dp+组合数)
    P3857 [TJOI2008]彩灯(线性基)
  • 原文地址:https://www.cnblogs.com/gfl-1112/p/12820421.html
Copyright © 2020-2023  润新知