老魏帮忙发的木棒问题的最大长度优先匹配原则算法
2011-06-22 17:14 废墟中的垃圾 阅读(409) 评论(0) 收藏 举报老魏帮忙发的问题的地址
http://www.cnblogs.com/eastjade/archive/2011/06/22/2086828.html
下面是算法:
定义最木棒的对象
class Item
{
public Item(int length, int count)
{
Length = length;
Count = count;
}
public int Length { get; set; }
public int Count { get; set; }
}
class Segment
{
public Segment()
{
Items = new List<int>();
}
public List<int> Items { get; set; }
public int Length
{
get { return Items.Sum(); }
}
public void RemoveLast()
{
Items.RemoveAt(Items.Count - 1);
}
}
定义一个MaximumFirstPermutation 类 作为控制类
class MaximumFirstPermutation
{
public MaximumFirstPermutation()
{
Items = new List<Item>();
}
private List<Item> backupItems;
public List<Item> Items { get; private set; }
public int SegmentLength { get; set; }
public Segment[] Segments { get; private set; }
/// <summary>
/// 将结果写入文件
/// </summary>
/// <param name="fileName"></param>
public void WriteToFile(string fileName)
{
StreamWriter writer = new StreamWriter(fileName);
List<int> allItems = new List<int>();
foreach (Segment segment in Segments)
{
writer.WriteLine(string.Concat(segment.Items.Select(i => i + " ")));
allItems.AddRange(segment.Items);
}
writer.WriteLine();
writer.WriteLine("---------------------------");
foreach (Item backupItem in backupItems)
{
Item usedItewm = Items.First(i => i.Length == backupItem.Length);
writer.WriteLine(string.Format("{0}: total {1}, used {2}, remaining {3}", backupItem.Length, backupItem.Count, allItems.Count(i => i == backupItem.Length), backupItem.Count - allItems.Count(i => i == backupItem.Length)));
}
writer.WriteLine();
writer.WriteLine("---------------------------");
writer.WriteLine(string.Format("total length: {0}, used {1}, remaining {2}", backupItems.Sum(i => i.Length * i.Count), allItems.Sum(), backupItems.Sum(i => i.Length * i.Count) - allItems.Sum()));
writer.Close();
}
public void Compute()
{
backupItems = Items.Select(i => new Item(i.Length, i.Count)).ToList();
Items = Items.OrderByDescending(i => i.Length).ToList();
List<Segment> segments = new List<Segment>();
while (true)
{
Segment segment = GetSegment(SegmentLength);
if (segment != null)
{
segments.Add(segment);
}
else
{
break;
}
}
Segments = segments.ToArray();
}
/// <summary>
/// 拼装过程
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
private Segment GetSegment(int length)
{
Segment segment = new Segment();
Item exact = Items.FirstOrDefault(i => i.Count > 0 && i.Length == length);
if (exact != null)
{
exact.Count--;
segment.Items.Add(exact.Length);
return segment;
}
foreach (Item item in Items.Where(i => i.Count > 0 && i.Length < length))
{
int count = 1;
while (true)
{
item.Count -= count;
for (int i = 1; i <= count; i++)
{
segment.Items.Add(item.Length);
}
bool exceeded = segment.Length > length;
if (!exceeded)
{
Segment remainingSegment = GetSegment(length - item.Length);
if (remainingSegment != null)
{
segment.Items.AddRange(remainingSegment.Items);
return segment;
}
}
item.Count += count;
for (int i = 1; i <= count; i++)
{
segment.RemoveLast();
}
if (exceeded)
{
break;
}
count++;
}
}
if (segment.Length != length)
{
return null;
}
return segment;
}
}
program.cs main 函数
MaximumFirstPermutation per = new MaximumFirstPermutation() { SegmentLength = 21 };
per.Items.Add(new Item(1, 100));
per.Items.Add(new Item(2, 200));
per.Items.Add(new Item(3, 90));
per.Items.Add(new Item(4, 14));
per.Items.Add(new Item(5, 25));
per.Items.Add(new Item(6, 6));
per.Items.Add(new Item(7, 20));
per.Items.Add(new Item(8, 35));
per.Items.Add(new Item(9, 15));
per.Items.Add(new Item(10, 21));
per.Items.Add(new Item(11, 22));
per.Items.Add(new Item(12, 9));
per.Items.Add(new Item(13, 16));
per.Items.Add(new Item(14, 35));
per.Items.Add(new Item(15, 39));
per.Items.Add(new Item(16, 41));
per.Items.Add(new Item(17, 29));
per.Items.Add(new Item(18, 26));
per.Items.Add(new Item(19, 18));
per.Items.Add(new Item(20, 20));
per.Items.Add(new Item(21, 35));
per.Compute();
per.WriteToFile(@"e:\r1.txt");
这个样例数据执行出来之后是
total length: 6479, used 6468, remaining 11
total Segment:48
浙公网安备 33010602011771号