平均分配算法之倒序贪婪

话说学校要将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直至数据分配结束

 

实现:

show #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

转载于:https://www.cnblogs.com/ivanyb/archive/2011/11/30/2269312.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分班是教学管理中一个重要的环节。如何分班才算平衡?相信很多人都想过这个问题,按总分高低排的方法只分得各班的总平均分基本平衡,但受偶然因素影响一些科目班之间平衡性很差,而学校评价教师教学成绩却以科目班的平衡性评价为主。 因此,我们都希望最好能分得每个科目各班都基本平衡,处理这个问题用手工根本难于做到,只有借助计算机的强大数据处理能力,我们才可能解决这个难题,下面示例数据就是最有力的说明,要观看示例效果请按下红色的[开始分班]键。即使你不用平衡各科分班,本软件也是一个又快又好地辅助分班的好助手。多谢使用本免费软件,并提出宝贵意见。??使用说明:先在表头填上要分开的班数,然后在下面的“要分班的原来学生成绩表”中输入学生的各科的成绩,最后按[开始分班]按钮,稍后你就可以在“结果表”中看到按平衡各科分班结果与按总分分班结果,以及两结果的对比预览表。 注意:1、性别一个字段是必须输入的数据;学号和姓名两个字段可选任一个字段输入,但最好能全部输入。?? 2、性别用“1”表示男,“0”表示女;学号最好能用前面数位表示班别,后两位数表示座号进行编号,以便分班后能方便查出原来所在的班级。?? 3、你最多可以输入19个班,每班77人,6个科目;1463个学生的成绩。科目名称可自行修改。?? 4、各科目的满分成绩不能超过100分,如果超过100分,应先把成绩折为100分,然后输入成绩。 本作者还制作有“教学成绩统计系统”、“课程表编排系统”、“数学工具箱”等软件,全部用EXCEL作为开发平台。????在使用过程中有什么问题,或有什么建议要求,请TET:(0757)8886326或E-mail:lixuedong@peoplemail.com.cn  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值