111,097
社区成员




var a = new MyList { { 250, 400 } };
你可以看到小板的排列位置也改变了。
主要的技术就是搞懂那个“算法”方法。
同时要搞懂 .net 的“迭代器”技术,它能帮助你写出精炼的查找算法的对外接口。这里也使用到了 Linq for object(where、min、max 等),帮助你精炼地写查找算法的内部逻辑。
这里也用了c#语言的针对集合结构的 Add 方法的“语法糖”,方便自己简化地书写集合对象的初始化代码(使用大括号语法来设置初始值)。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var s = new MyList { { 100, 200 }, { 100, 200 }, { 100, 1500 }, { 30, 50 }, { 40, 80 } };
var a = new MyList { { 250, 800 } };
var result = 排列(a.List, s.List);
Console.WriteLine("输出排列:");
var cnt = 0;
foreach (var r in result)
{
Console.WriteLine($"第 {++cnt,2} 块:x={r.X} y={r.Y} w={r.Width} h={r.Height}");
}
}
static IEnumerable<Block> 排列(List<Block> 阴影, List<Block> 待排列)
{
foreach (var x in 待排列)
{
var 宽度适配 = 阴影.Where(b => b.Width >= x.Width).ToList();
if (宽度适配.Count > 0)
{
var 最小宽度 = 宽度适配.Min(b => b.Width);
var 高度适配 = 阴影.Where(b => b.Width == 最小宽度 && b.Height >= x.Height).ToList();
if (高度适配.Count > 0)
{
var 最小高度 = 高度适配.Min(b => b.Height);
var find = 阴影.Where(b => b.Width == 最小宽度 && b.Height == 最小高度).FirstOrDefault(); //要把x放入这块儿矩形里边
if (find != null) //如果当前的x无法放入,则跳过它
{
阴影.Remove(find);
if (find.Width - x.Width > 0)
阴影.Add(new Block { X = find.X + x.Width, Y = find.Y, Width = find.Width - x.Width, Height = x.Height });
if (find.Height - x.Height > 0)
阴影.Add(new Block { X = find.X, Y = find.Y + x.Height, Width = x.Width, Height = find.Height - x.Height });
if (find.Width - x.Width > 0 && find.Height - x.Height > 0)
阴影.Add(new Block { X = find.X + x.Width, Y = find.Y + x.Height, Width = find.Width - x.Width, Height = find.Height - x.Height });
x.X = find.X;
x.Y = find.Y;
yield return x;
}
}
}
}
}
}
public class MyList : IEnumerable<Block>
{
public void Add(int w, int h)
{
List.Add(new Block { Width = w, Height = h });
}
public List<Block> List = new List<Block>();
public IEnumerator<Block> GetEnumerator()
{
return List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Block
{
public int X;
public int Y;
public int Width;
public int Height;
}
}
这里,首先假设“大阴影”只有一块,宽和高为250x800,要放入5块小板,调用算法“排列”来输出所有能放入阴影的小板列表。
从输出可以看到,输出了4块小板,分别在原来小板 Block 数据结构中填写上了 .X 和 .Y 坐标属性值。而有一块小板无法放入。
算法其实是很简单的贪心算法:首先寻找宽度最小的阴影,然后在宽度最小的那些阴影中寻找高度最小的阴影,最后将小板放入这块阴影(将阴影从列表中Remove掉,替换插入1、3、0个新的阴影)。如此迭代遍历所有小板。