很多场景算红包的要求:根本问题就是指定的钱,指定的个数,红包发完,钱不剩余,最小红包1分钱,最大也需要限制。

开源是程序员的基本美德

  1         int pp = 100;//元换算成分的比例
  2
  3             int total =(int)((decimal)10 * pp);//红包总额 
  4             int num = 8;//红包个数
  5             int min = (int)((decimal)0.02 * pp);//红包不少于
  6             int max = (int)((decimal)2 * pp);//最大红包不超过 
  7
  8             if (min <= 0 && min >= (total - max) / (num - 1))
  9             {
 10                 Console.WriteLine($"红包最小值异常:{total}分{num}个红包,最小值必须大于0,且不能小余{(total - max) / (num - 1)/100f}");
 11                 return;
 12             }
 13             if (num * min > total)
 14             {
 15                 Console.WriteLine($"红包最小值异常:{total}分{num}个红包,红包最小值不能超过{total / num / 100f}");
 16                 return;
 17             }
 18             if (num * max < total)
 19             {
 20                 Console.WriteLine($"红包最大值异常:{total}分{num}个红包,红包最大值不能小余{total / num / 100f}");
 21                 return;
 22             }
 23             if (max > total - min * (num - 1))
 24             {
 25                 Console.WriteLine($"红包最大值异常:{total}分{num}个红包,红包最大值不能超过{(total - min * (num - 1)) / 100f}");
 26                 return;
 27             }
 28
 29             float[] ret = new float[num];
 30             ret[0] = 0;
 31             int i = 1;
 32             //下面不考虑随机数的唯一性,给每个人都预留最少的钱
 33             int totalByHundred = total - (num * min);
 34             Random random = new Random();
 35             while (i < num)
 36             {
 37                 ret[i] = random.Next(totalByHundred);
 38                 i++;
 39             }
 40             //先从大到小排序  将差值计算出来+最先预留的min值
 41             Array.Sort(ret);
 42             i = 0;
 43             while (i < num - 1)
 44             {
 45                 ret[i] = (ret[i + 1] - ret[i] + min);//每个人都预留最少的钱
 46                 i++;
 47             }
 48             ret[i] = (totalByHundred - ret[i] + min);//最后一个 仍然是最大可分值-自身+min值即可。
 49             //再次排序金额  将超出最大值的金额 全部重新赋值,并将差值累加给tempmax ,然后将tempmax再依次随机分给最小的金额
 50             Array.Sort(ret);
 51             float tempmax = 0;
 52             for (int k = ret.Length - 1; k >= 0; k--)
 53             {
 54                 if (ret[k] > max)
 55                 {
 56                     float t = random.Next(min,max);
 57                     tempmax += ret[k] - t;
 58                     ret[k] = t;
 59                 }
 60                 else
 61                 {
 62                     break;
 63                 }
 64             }
 65             //分完为止  可能运气好  没有可分的 
 66             while (tempmax > 0)
 67             {
 68                 Console.WriteLine("触发平均算法执行");
 69                 Array.Sort(ret);
 70                 for (int k = 0; k < ret.Length; k++)
 71                 {
 72                     //一轮分不完  将再次排序再分  tempmax为0即可
 73                     if (tempmax > 0)
 74                     {
 75                         int tm = max - (int)ret[k];
 76                         if (tempmax< tm)
 77                         {
 78                             //此处判断非常重要 
 79                             ret[k] = ret[k] + tempmax;
 80                             tempmax = 0;
 81                         }
 82                         else
 83                         {
 84                             float t = random.Next(tm);
 85                             ret[k] = ret[k] + t;
 86                             tempmax -= t;
 87                         }
 88                     }
 89                     else
 90                     {
 91                         break;
 92                     }
 93                 }
 94             }
 95
 96             //最后利用洗牌算法进行打乱数组
 97             int currentIndex;
 98             float tempValue;
 99             for (int j = 0; j < ret.Length; j++)
100             {
101                 currentIndex = random.Next(0, ret.Length - j);
102                 tempValue = ret[currentIndex];
103                 ret[currentIndex] = ret[ret.Length -1- j];
104                 ret[ret.Length-1 - j] = tempValue;
105             }
106             //完美
107             for (int j = 0; j < ret.Length; j++)
108             {
109                 Console.WriteLine($"第{j + 1}个红包:金额{(ret[j] / 100f)}元");
110             }
111             //最后检查总红包金额以及最大最小红包是否符合要求  肯定符合要求的  只是输出看一下
112             Console.WriteLine($"红包总金额:{(ret.Sum() / 100f).ToString("F2")}元,红包最大值:{ret.Max() / 100f}元,红包最小值:{ret.Min() / 100f}元");

该算法由C#写成,更多交流请关注原文博客地址:

红包算法的一种

 
12-17 08:36