话说学校要将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
结果: