你好,我希望有人会帮我这个=): 我有一些数字,我需要将它们分成两组,大约相等的总和,并将第一组分配为“1”,第二组分配“0”,然后将每组分成相同的方式进入子组,直到子组为止来自集合的数字之一!
图片解释这个疯狂的事情): pict
答案 0 :(得分:2)
这是基本算法,如果你知道C#,那么它很容易理解。程序在浏览树时打印分区。
请注意,存在一些可能的错误,而且代码距离教师对作业的期望质量还有几年的距离。 (因为我猜这是一个家庭作业......如果它是为了工作,那就更糟了,我的代码几乎是Daily-WTF质量)
但它应该让你了解基本的算法结构,知道:
代码:
var symbols = new[] {
new Symbol { Text = "A", Count=15, Probability=double.NaN, Code=""},
new Symbol { Text = "B", Count=7, Probability=double.NaN, Code="" },
new Symbol { Text = "C", Count=6, Probability=double.NaN, Code="" },
new Symbol { Text = "D", Count=6, Probability=double.NaN, Code="" },
new Symbol { Text = "E", Count=5, Probability=double.NaN, Code="" },
}.ToList();
Func<IEnumerable<Symbol>, int> totalCount =
symbols_ => symbols_.Aggregate(0, (a, s) => a + s.Count);
var total = totalCount(symbols);
foreach(var symbol in symbols)
{
symbol.Probability = total / symbol.Count;
}
//symbols.Sort((a, b) => b.Count.CompareTo(a.Count));
// Where is the Y-Combinator when you need it ?
Action<IEnumerable<Symbol>, string, int> recurse = null;
recurse = (symbols_, str, depth) => {
if (symbols_.Count() == 1)
{
symbols_.Single().Code = str;
return;
}
var bestDiff = int.MaxValue;
int i;
for(i = 1; i < symbols_.Count(); i++)
{
var firstPartCount = totalCount(symbols_.Take(i));
var secondPartCount = totalCount(symbols_.Skip(i));
var diff = Math.Abs(firstPartCount - secondPartCount);
if (diff < bestDiff) bestDiff = diff;
else break;
}
i = i - 1;
Console.WriteLine("{0}{1}|{2}", new String('\t', depth),
symbols_.Take(i).Aggregate("", (a, s) => a + s.Text + " "),
symbols_.Skip(i).Aggregate("", (a, s) => a + s.Text + " "));
recurse(symbols_.Take(i), str + "0", depth+1);
recurse(symbols_.Skip(i), str + "1", depth+1);
};
recurse(symbols, "", 0);
Console.WriteLine(new string('-', 78));
foreach (var symbol in symbols)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}", symbol.Code, symbol.Text,
symbol.Count, symbol.Probability);
}
Console.ReadLine();