平均分配算法之倒序贪婪
话说学校要将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
结果:
人生无处不PK