/// <summary> /// Поиск оптимального маршрута с посещением всех веток метро с помощью метода ветвей и границ /// </summary> /// <param name="scheme"></param> /// <returns></returns> public IEnumerable <IRoute> VisitAllLinesByBranchAndBound(Scheme scheme) { if (scheme == null) { throw new ArgumentNullException(); } var stations = scheme.GetAllLineRelationStations(); // Все пересадочные станции всех веток var lines = scheme.GetLines().ToArray(); // все ветки метро var linesStations = new Station[lines.Length][]; // массив станций переходов для каждой ветки var indeces = new int[lines.Length]; // индекс станции для каждой ветки for (var i = 0; i < lines.Length; ++i) { linesStations[i] = lines[i].GetRelationStations().ToArray(); indeces[i] = 0; } var lastLineInd = indeces.Length - 1; var cache = new RoutesCollection <Station>((r) => new TwoItemsKey <Station>(r.From, r.To)); var visitor = new AllLinesVisitor(); int counter = 0; int skipped = 0; bool next = true; do { // Обработка станций var routes = new List <IRoute>(); for (int fromLineId = 0; fromLineId < indeces.Length - 1; ++fromLineId) { var fromStation = linesStations[fromLineId][indeces[fromLineId]]; for (int toLineId = fromLineId + 1; toLineId < indeces.Length; ++toLineId) { var toStation = linesStations[toLineId][indeces[toLineId]]; IRoute route; if (!cache.TryGetRoute(fromStation, toStation, out route)) { route = FindRoute(fromStation, toStation); cache.Add(route); } routes.Add(route); } } visitor.Push(routes); counter++; /* * // ограничение маршрутов для тестирования * if (counter > 10) * next = false; */ // Переход к следующей комбинации var lineInd = lastLineInd; do { ++indeces[lineInd]; if (indeces[lineInd] >= linesStations[lineInd].Length) { if (lineInd == 0) { // перебраны все возможные комбинации next = false; break; } else { indeces[lineInd] = 0; } } else { break; } --lineInd; }while (lineInd >= 0); }while (next); visitor.Complete(); visitor.Completion.Wait(); return(visitor.GetResults()); }
public void Add(IRoute route) { _routes.Add(route); _lines.Add(route.From.Line); _lines.Add(route.To.Line); }