在一个LINQ查询中使用最近邻算法解决旅行商问题?

Chr*_*sJJ 5 .net c# linq

特定

List<Point> cities = /* ... */ ;
double distance(Point a, Point b) { /* ... */ };
Run Code Online (Sandbox Code Playgroud)

有没有一个LINQ查询返回最近邻算法的旅行商最短路径作为List<int>指数cities

Tho*_*que 3

我认为您不能在单个查询中完成所有操作,算法的某些部分必须单独实现。

这是一个强力实现,它检查所有城市排列并返回访问所有城市的最短路径:

var bestPath =
   cities.Permutations()
      .MinBy(
        steps => steps.Aggregate(
                    new { Sum = 0, Previous = default(Point) },
                    (acc, c) =>
                        new
                        {
                            Sum = acc.Sum + (acc.Previous != null ? Distance(c, acc.Previous) : 0 ),
                            Previous = c
                        },
                    acc => acc.Sum));
Run Code Online (Sandbox Code Playgroud)

扩展Permutations方法定义如下:

public static IEnumerable<IEnumerable<T>> Permutations<T>(this IEnumerable<T> source)
{
    var query =
        from item in source
        from others in source.SkipOnce(item).Permutations()
        select new[] { item }.Concat(others);
    return query.DefaultIfEmpty(Enumerable.Empty<T>());
}

public static IEnumerable<T> SkipOnce<T>(this IEnumerable<T> source, T itemToSkip)
{
    bool skipped = false;
    var comparer = EqualityComparer<T>.Default;
    foreach (var item in source)
    {
        if (!skipped && comparer.Equals(item, itemToSkip))
            skipped = true;
        else
            yield return item;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,有更好的方法来解决这个问题,但是这个是有效的......其中大部分是在单个查询中,唯一单独实现的部分并不特定于当前的问题,并且可以重用于其他任务。

编辑:哎呀,我刚刚意识到我也使用了非标准MinBy方法;你可以在 MoreLinq 项目中找到它