平均分配算法之倒序贪婪


话说学校要将100小学升初中的学生分配到4个初一班级里面,分配完以后这四个班级语文、数学两科之和的平均分要基本相同。

分析:

学生两科分数都在100到0分不等,那么只需要在分配以后保证每个班级的总分基本等于 100个学生的语文+数学总分/4就可以保证每个班级的平均分基本相同

算法思想:

目的:把m份数据分配到n个人的头上,m份数据里面的数据大小个不相同

过程:
1.1 把待分配的数据m从大到小排序;
1.2 从数据m取出n份做为初始值分配给n个人;
1.3 把这n个人的数据从小到大排序;
1.4 从数据m再取出n份数据累加到n个人的头上
1.5 重复1.3-1.4直至数据分配结束

 

实现:

 #region show

    /// <summary>
    /// 倒序贪婪平均分配算法
    /// </summary>
    class Tanlan
    {
        static void Main(string[] args)
        {
            int n = 10;
            List<int> list = new GetRadon().CreateRadon(); //new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //
            //new TanlanA().SortAsc1(list);
            //for (int i = 0; i < list.Count; i++)
            //{
            //    Console.WriteLine(list[i]);
            //}
            int t = list.Sum();
            Console.WriteLine("倒序贪婪平均分配算法 总数:{0} 分配给{1}人的平均值:{2}", t, n, t / n);
            new TanlanA().Distrube(list, n);

            Console.ReadLine();
        }
    }

    class GetRadon
    {
        public List<int> CreateRadon()
        {
            List<int> list = new List<int>();
            Random r = new Random();
            //for (int i = 1; i <= 10000; i++)
            //{
            //    int n = r.Next(0, 100000);
            //    list.Add(n);
            //}

            for (int i = 0; i < 100; i++)
            {
                int n = r.Next(0, 101);
                list.Add(n);
            }

            return list;
        }

    }

    class TanlanA
    {
        public void SortDesc(List<int> list)
        {
            for (int i = 0; i < list.Count - 1; i++)
            {
                int maxindex = i;
                for (int j = i + 1; j < list.Count; j++)
                {
                    if (list[maxindex] < list[j])
                    {
                        maxindex = j;
                    }
                }
                int t = list[i];
                list[i] = list[maxindex];
                list[maxindex] = t;
            }
        }

        public void SortAsc(List<int> list, List<List<int>> slist)
        {
            for (int i = 0; i < list.Count - 1; i++)
            {
                int miindex = i;
                for (int j = i + 1; j < list.Count; j++)
                {
                    if (list[miindex] > list[j])
                    {
                        miindex = j;
                    }
                }
                int t = list[i];
                list[i] = list[miindex];
                list[miindex] = t;

                List<int> tmp = slist[i];
                slist[i] = slist[miindex];
                slist[miindex] = tmp;
            }
        }

        /// <summary>
        /// 倒序贪婪
        /// </summary>
        /// <param name="list"></param>
        /// <param name="count"></param>
        public void Distrube(List<int> list, int count)
        {
            if (list.Count < count)
            {
                Console.WriteLine("分配的list大小必须大于等于分组数");
                return;
            }
            List<int> sumlist = new List<int>();//保存分组的总和,方便根据其值进行从小到大排序
            List<List<int>> slist = new List<List<int>>();//保存分组的所有分配到的值

            SortDesc(list);//先将list按照从大到小排序

            int n = 0;
            int c = 0;
            for (int i = 0; i < list.Count; i += count)//每次取count步长的值
            {
                n++;
                c = 0;
                for (int j = i; j < n * count; j++)//将count步长中的值从0开始一个个赋予每个分组
                {
                    if (j >= list.Count) break;
                    int y = (j + 1) % count;

                    if (sumlist.Count < count)
                    {
                        sumlist.Add(list[j]);
                        slist.Add(new List<int>() { list[j] });
                    }
                    else
                    {
                        sumlist[c] += list[j];
                        slist[c].Add(list[j]);
                        c++;
                    }
                }

                SortAsc(sumlist, slist);//对分组进行从小到大排序

            }
            for (int jj = 0; jj < slist.Count; jj++)
            {
                Console.WriteLine("班级{1} 总分:{0}", slist[jj].Sum(), jj + 1);
                string[] arr = Array.ConvertAll(slist[jj].ToArray(), new Converter<int, string>((iii) => { return iii.ToString(); }));
                Console.WriteLine(string.Join(",", arr));
            }
        }
    }
    #endregion


结果:

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值