Non penso che si possa fare tutto in una singola query, alcune parti degli algoritmi dovranno essere implementate separatamente.
Ecco un'implementazione di forza bruta che prende in esame tutte le permutazioni della città e restituisce il percorso più breve che visita tutte le città:
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));
Il metodo Permutations
interno è definito come segue:
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;
}
}
Di Certo, ci sono degli approcci molto migliori per risolvere questo problema, ma questo funziona ... La maggior parte si trova in una singola query, le uniche parti che sono implementate separatamente non sono specifiche del problema in questione e possono essere riutilizzate per altre attività.
MODIFICA: oops, ho appena realizzato che ho utilizzato anche il metodo non standard MinBy
; lo si può trovare in the MoreLinq project
fonte
2011-09-24 12:37:23
per "vicino più prossimo" pensi di "andare al prossimo citiy più vicino"? Beh, puoi sicuramente farlo con una catena di linq, ma questo quasi si legge come * compiti a casa * ... – Carsten