Пример #1
0
        //Ищет все столкновения на станциях.
        public static IEnumerable <CollisionAtStationCase> FindCollisionsAtStations(ITransportNetwork transportNetwork, IEnumerable <IRoute> routes)
        {
            //Для каждой станции запоминаем маршруты, проходящие через нее, а также расстояние, которое необходимо пройти по маршруту, чтобы добраться до данной станции.
            BucketDictionary <int, Tuple <IRoute, int> > routesPassingThroughStation = new BucketDictionary <int, Tuple <IRoute, int> >();

            foreach (IRoute route in routes)
            {
                for (int i = 0; i < route.StationsCount; i++)
                {
                    routesPassingThroughStation.Add(route[i], new Tuple <IRoute, int>(route, GetRouteLength(transportNetwork, route, 0, i)));
                }
            }

            //Обходим каждую станцию и смотрим, есть ли такая пара маршрутов, проходящих через данную станцию, расстояние до данной станции которых одинаково.
            //Такая пара маршрутов столкнется в рассматриваемой станции.
            List <CollisionAtStationCase> collisionAtStationCases = new List <CollisionAtStationCase>();

            //Для каждой пары (Станция; Все маршруты, проходящие через станцию).
            foreach (KeyValuePair <int, List <Tuple <IRoute, int> > > possibleCases in routesPassingThroughStation)
            {
                //Текущая станция.
                int currentStation = possibleCases.Key;
                //Все маршруты, проходящие через текущую станцию.
                List <Tuple <IRoute, int> > routesList = possibleCases.Value;

                //Смотрим все возможные пары машрутов.
                for (int i = 0; i < routesList.Count - 1; i++)
                {
                    for (int j = i + 1; j < routesList.Count; j++)
                    {
                        //Если расстояние, которое необходимо пройти по первому маршруту, чтобы добраться до текущей станции, аналогично расстоянию второго маршрута, то маршруты сталкиваются.
                        if (routesList[i].Item2 == routesList[j].Item2)
                        {
                            collisionAtStationCases.Add(new CollisionAtStationCase(currentStation, routesList[i].Item1, routesList[j].Item1));
                        }
                    }
                }
            }

            return(collisionAtStationCases);
        }
Пример #2
0
        //Ищет все столкновения на путях.
        public static IEnumerable <CollisionOnConnectionBetweenStationsCase> FindCollisionsOnConnectionsBetweenStations(ITransportNetwork transportNetwork, IEnumerable <IRoute> routes)
        {
            //Для каждого пути между станциями запоминаем маршруты, проходящие через данный путь.
            BucketDictionary <Tuple <int, int>, Tuple <IRoute, int> > routesPassingThroughConnection = new BucketDictionary <Tuple <int, int>, Tuple <IRoute, int> >();
            //Если существует путь, через который уже прошли некоторые маршруты, и мы встречаем, маршрут, который проходит данный путь в обратном направлении, то данный маршрут записывается
            //в нижеуказанную структуру.
            BucketDictionary <Tuple <int, int>, Tuple <IRoute, int> > routesPassingThroughConnectionInOppositeDirection = new BucketDictionary <Tuple <int, int>, Tuple <IRoute, int> >();

            //Запоминаем, какие маршруты проходят через каждый путь и в каком направлении, а также расстояние, которое необходимо пройти по маршруту, чтобы добраться до пути.
            foreach (IRoute route in routes)
            {
                for (int i = 0; i < route.StationsCount - 1; i++)
                {
                    Tuple <int, int> connectionKey         = new Tuple <int, int>(route[i], route[i + 1]);
                    Tuple <int, int> oppositeConnectionKey = new Tuple <int, int>(route[i + 1], route[i]);

                    Tuple <IRoute, int> passingCase = new Tuple <IRoute, int>(route, GetRouteLength(transportNetwork, route, 0, i));

                    if (routesPassingThroughConnection.ContainsKey(oppositeConnectionKey))
                    {
                        routesPassingThroughConnectionInOppositeDirection.Add(connectionKey, passingCase);
                    }
                    else
                    {
                        routesPassingThroughConnection.Add(connectionKey, passingCase);
                    }
                }
            }

            //Обходим каждый путь и смотрим, есть ли такая пара маршрутов, которая прошла данный путь в противоположных друг другу направлениях
            List <CollisionOnConnectionBetweenStationsCase> collisionBetweenStationsCases = new List <CollisionOnConnectionBetweenStationsCase>();

            foreach (KeyValuePair <Tuple <int, int>, List <Tuple <IRoute, int> > > possibleCases in routesPassingThroughConnection)
            {
                Tuple <int, int> connectionKey         = possibleCases.Key;
                Tuple <int, int> oppositeConnectionKey = new Tuple <int, int>(connectionKey.Item2, connectionKey.Item1);

                //Если все маршруты, проходящие через рассматриваемый путь, проходят его в одном направлении, то, очевидно, на этом пути никакие маршруты не столкнутся
                //(условием столкновения поездов на пути является их движение навстречу друг к другу).
                if (!routesPassingThroughConnectionInOppositeDirection.ContainsKey(oppositeConnectionKey))
                {
                    continue;
                }

                List <Tuple <IRoute, int> > routesList         = possibleCases.Value;
                List <Tuple <IRoute, int> > oppositeRoutesList = routesPassingThroughConnectionInOppositeDirection[oppositeConnectionKey];

                //Для каждого маршрута, проходящего данный путь, смотрим все маршруты, проходящие данный путь в противоположном направлении.
                int maxAllowedDifferenceInDistance = transportNetwork.GetConnectionLengthBetweenStations(connectionKey.Item1, connectionKey.Item2);
                foreach (Tuple <IRoute, int> route in routesList)
                {
                    foreach (Tuple <IRoute, int> oppositeRoute in oppositeRoutesList)
                    {
                        int distancesToPassDifference = Math.Abs(route.Item2 - oppositeRoute.Item2);
                        //Если расстояние, которое необходимо пройти по первому маршруту, не превышает расстояния, которое необходимо пройти по второму, на величину,
                        //бОльшую длины рассматриваемого пути, то маршруты сталкиваются.
                        if (distancesToPassDifference < maxAllowedDifferenceInDistance)
                        {
                            collisionBetweenStationsCases.Add(new CollisionOnConnectionBetweenStationsCase(new CollisionOnConnectionBetweenStationsCase.Connection(connectionKey.Item1, connectionKey.Item2), route.Item1, oppositeRoute.Item1));
                        }
                    }
                }
            }

            return(collisionBetweenStationsCases);
        }