public static bool CanChangePlane(List <Airline> AirlineList)
        {
            int StartIndex, EndIndex;
            var range = CoreAlgorithm.GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            if (StartIndex <= 0 || EndIndex == -1)
            {
                return(false);
            }

            /*StartIndex 是受   台风影响的航班
             * EndIndex   是不受 台风影响的航班!
             * 空飞航班起点在 StartIndex,终点在 EndIndex
             * 第一:机型相同(不同机型惩罚太大)
             * 第二:被取代的航班的飞机,其被取代航班的前期航班,能有一个目的地为当前调整航班台风后的机场的机会
             * 第三:代价不能太大*/

            var CurrentAirline  = AirlineList[StartIndex - 1];
            var MinTakeOffTime  = CurrentAirline.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
            var Airport         = CurrentAirline.EndAirPort;
            var orgPlaneType    = CurrentAirline.PlaneType;
            int MinScore        = int.MaxValue;
            var OrgAirlineList  = new List <Airline>();
            var RepAirlineList  = new List <Airline>();
            var BaseAirlineList = new List <Airline>();
            var OrgAirlineIdx   = new List <int>();
            var RepAirlineIdx   = new List <int>();
            var BaseIdx         = new List <int>();

            foreach (var info in AirportIdAirlineDic[Airport])
            {
                //机型相同(不同机型惩罚太大)
                if (info.IsTakeOff && info.EventTime >= MinTakeOffTime && info.EventAirline.PlaneType == orgPlaneType)
                {
                    //已经有调机或者取消的情况,则跳过
                    if (CoreAlgorithm.EmptyFlyList.Count((x => { return(x.ModifiedPlaneID == info.EventAirline.ModifiedPlaneID); })) == 1)
                    {
                        continue;
                    }
                    if (Solution.PlaneIdAirlineDic[info.EventAirline.ModifiedPlaneID].Count((x => { return(x.FixMethod == enmFixMethod.Cancel); })) > 0)
                    {
                        continue;
                    }
                    var ReplaceAirline = Solution.PlaneIdAirlineDic[info.EventAirline.ModifiedPlaneID];
                    //被取代的航班的飞机,其被取代航班的前期航班,能有一个目的地为当前调整航班台风后的机场的机会
                    for (int org = EndIndex; org < AirlineList.Count; org++)
                    {
                        //遍历原来航班的台风后的航班(包括台风后的第一个航班)
                        //当前被替代航班为止(倒序,越接近越好)
                        var replbase = 0; //被取代航班索引号
                        for (int i = 0; i < ReplaceAirline.Count; i++)
                        {
                            if (ReplaceAirline[i].ID == info.EventAirline.ID)
                            {
                                replbase = i;
                            }
                        }

                        for (int rep = replbase - 1; rep > 0; rep--)
                        {
                            if (ReplaceAirline[rep].EndAirPort.Equals(AirlineList[org].EndAirPort))
                            {
                                var Score = replbase - rep + org - EndIndex;

                                /*
                                 * Console.Write("被取代航班在原飞行计划中的索引:" + RepIdx);
                                 * Console.WriteLine("  前导航班索引:" + rep + "  间隔航班数:" + (RepIdx - rep));
                                 * Console.WriteLine("被前导航班:" + ReplaceAirline[rep].ToString());
                                 * Console.Write("台风后续首航班索引:" + EndIndex);
                                 * Console.WriteLine("台风后续目标航班索引:" + org + "  间隔航班数:" + (org - EndIndex));
                                 * Console.WriteLine("总体偏差:" + Score);
                                 */
                                if (Score < MinScore)
                                {
                                    OrgAirlineList.Clear();
                                    RepAirlineList.Clear();
                                    BaseAirlineList.Clear();
                                    OrgAirlineIdx.Clear();
                                    RepAirlineIdx.Clear();
                                    BaseIdx.Clear();
                                    MinScore = Score;
                                    OrgAirlineList.Add(AirlineList[org]);
                                    RepAirlineList.Add(ReplaceAirline[rep]);
                                    BaseAirlineList.Add(info.EventAirline);
                                    OrgAirlineIdx.Add(org);
                                    RepAirlineIdx.Add(rep);
                                    BaseIdx.Add(replbase);
                                }
                                else
                                {
                                    if (Score == MinScore)
                                    {
                                        OrgAirlineList.Add(AirlineList[org]);
                                        RepAirlineList.Add(ReplaceAirline[rep]);
                                        BaseAirlineList.Add(info.EventAirline);
                                        OrgAirlineIdx.Add(org);
                                        RepAirlineIdx.Add(rep);
                                        BaseIdx.Add(replbase);
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
            }
            if (OrgAirlineList.Count != 0)
            {
                //选择基准时间最早的航班,理由如下
                //在衔接的时候,越是早交换,则越可以避免过站时间不足的问题
                var SetIdx             = 0;
                var OrgPlandId         = AirlineList[0].ModifiedPlaneID;
                var RelPlaneId         = BaseAirlineList[SetIdx].ModifiedPlaneID;
                var ReplaceAirlineList = Solution.PlaneIdAirlineDic[RelPlaneId];
                //取消的时候牵涉到台风场景
                if (CheckCondition.TyphoonAirport.Contains(ReplaceAirlineList[RepAirlineIdx[SetIdx]].EndAirPort))
                {
                    return(false);
                }
                if (CheckCondition.TyphoonAirport.Contains(AirlineList[OrgAirlineIdx[SetIdx]].EndAirPort))
                {
                    return(false);
                }
                //飞机航线的测试
                for (int i = BaseIdx[SetIdx]; i < ReplaceAirlineList.Count; i++)
                {
                    if (!CheckCondition.IsAirlinePlaneAvalible(ReplaceAirlineList[i].StartAirPort, ReplaceAirlineList[i].EndAirPort, OrgPlandId))
                    {
                        return(false);
                    }
                }
                for (int i = OrgAirlineIdx[SetIdx] + 1; i < AirlineList.Count; i++)
                {
                    if (!CheckCondition.IsAirlinePlaneAvalible(AirlineList[i].StartAirPort, AirlineList[i].EndAirPort, RelPlaneId))
                    {
                        return(false);
                    }
                }
                var AirlineListClone        = Utility.DeepCopy(AirlineList);
                var ReplaceAirlineListClone = Utility.DeepCopy(ReplaceAirlineList);
                //1.从StartIndex开始,到ORG为止的航班取消掉
                for (int i = StartIndex; i < OrgAirlineIdx[SetIdx] + 1; i++)
                {
                    AirlineListClone[i].FixMethod = enmFixMethod.Cancel;
                }
                //2.被取代的部分取消
                for (int i = RepAirlineIdx[SetIdx] + 1; i < BaseIdx[SetIdx]; i++)
                {
                    ReplaceAirlineListClone[i].FixMethod = enmFixMethod.Cancel;
                }
                //3.取代操作(取代者)
                for (int i = BaseIdx[SetIdx]; i < ReplaceAirlineList.Count; i++)
                {
                    ReplaceAirlineListClone[i].ModifiedPlaneID = OrgPlandId;
                }
                //4.取代操作(被取代者)
                for (int i = OrgAirlineIdx[SetIdx] + 1; i < AirlineList.Count; i++)
                {
                    AirlineListClone[i].ModifiedPlaneID = RelPlaneId;
                }

                var NewOrgPlaneList = new List <Airline>();
                var NewRelPlaneList = new List <Airline>();
                for (int i = 0; i < AirlineListClone.Count; i++)
                {
                    if (AirlineListClone[i].ModifiedPlaneID == OrgPlandId)
                    {
                        NewOrgPlaneList.Add(AirlineListClone[i]);
                    }
                    if (AirlineListClone[i].ModifiedPlaneID == RelPlaneId)
                    {
                        NewRelPlaneList.Add(AirlineListClone[i]);
                    }
                }
                for (int i = 0; i < ReplaceAirlineListClone.Count; i++)
                {
                    if (ReplaceAirlineListClone[i].ModifiedPlaneID == OrgPlandId)
                    {
                        NewOrgPlaneList.Add(ReplaceAirlineListClone[i]);
                    }
                    if (ReplaceAirlineListClone[i].ModifiedPlaneID == RelPlaneId)
                    {
                        NewRelPlaneList.Add(ReplaceAirlineListClone[i]);
                    }
                }
                NewOrgPlaneList.Sort((x, y) => { return(x.ModifiedEndTime.CompareTo(y.ModifiedStartTime)); });
                NewRelPlaneList.Sort((x, y) => { return(x.ModifiedEndTime.CompareTo(y.ModifiedStartTime)); });

                //检查时间间隔
                for (int i = 0; i < NewOrgPlaneList.Count; i++)
                {
                    if (i != 0)
                    {
                        if (NewOrgPlaneList[i].PlaneID != NewOrgPlaneList[i].ModifiedPlaneID)
                        {
                            if (NewOrgPlaneList[i].ModifiedStartTime.Subtract(NewOrgPlaneList[i - 1].ModifiedEndTime).TotalMinutes < Utility.StayAtAirPortMinutes)
                            {
                                return(false);
                            }
                        }
                    }
                }

                for (int i = 0; i < NewRelPlaneList.Count; i++)
                {
                    if (i != 0)
                    {
                        if (NewRelPlaneList[i].PlaneID != NewRelPlaneList[i].ModifiedPlaneID)
                        {
                            if (NewRelPlaneList[i].ModifiedStartTime.Subtract(NewRelPlaneList[i - 1].ModifiedEndTime).TotalMinutes < Utility.StayAtAirPortMinutes)
                            {
                                return(false);
                            }
                        }
                    }
                }
                //1.从StartIndex开始,到ORG为止的航班取消掉
                for (int i = StartIndex; i < OrgAirlineIdx[SetIdx] + 1; i++)
                {
                    AirlineList[i].FixMethod = enmFixMethod.Cancel;
                }
                //2.被取代的部分取消
                for (int i = RepAirlineIdx[SetIdx] + 1; i < BaseIdx[SetIdx]; i++)
                {
                    ReplaceAirlineList[i].FixMethod = enmFixMethod.Cancel;
                }
                //3.取代操作(取代者)
                for (int i = BaseIdx[SetIdx]; i < ReplaceAirlineList.Count; i++)
                {
                    ReplaceAirlineList[i].ModifiedPlaneID = OrgPlandId;
                    ReplaceAirlineList[i].FixMethod       = enmFixMethod.ChangePlane;
                }
                //4.取代操作(被取代者)
                for (int i = OrgAirlineIdx[SetIdx] + 1; i < AirlineList.Count; i++)
                {
                    AirlineList[i].ModifiedPlaneID = RelPlaneId;
                    AirlineList[i].FixMethod       = enmFixMethod.ChangePlane;
                }
                //5.Solution的飞机表更新
                Solution.PlaneIdAirlineDic[OrgPlandId].Clear();
                Solution.PlaneIdAirlineDic[RelPlaneId].Clear();
                foreach (var airline in AirlineList)
                {
                    Solution.PlaneIdAirlineDic[airline.ModifiedPlaneID].Add(airline);
                }
                foreach (var airline in ReplaceAirlineList)
                {
                    Solution.PlaneIdAirlineDic[airline.ModifiedPlaneID].Add(airline);
                }

                Console.WriteLine(OrgPlandId + "->" + RelPlaneId);

                return(true);
            }
            return(false);
        }
Esempio n. 2
0
        static ExchangeRecord ExchangeEvaluateAdvance(string firstPlaneId, string secondPlandId)
        {
            ExchangeRecord Rtn = new ExchangeRecord();

            Rtn.DiffScore = 0;

            List <Airline> first  = Solution.PlaneIdAirlineDic[firstPlaneId];
            List <Airline> second = Solution.PlaneIdAirlineDic[secondPlandId];
            //测试一下当前分数:
            double FirstScore         = scoreDic[firstPlaneId];
            double SecondScore        = scoreDic[secondPlandId];
            var    TotalScore         = FirstScore + SecondScore;
            var    FirstTyphoonRange  = CoreAlgorithm.GetTyphoonRange(first);
            var    SecondTyphonnRange = CoreAlgorithm.GetTyphoonRange(second);

            for (int firstIdx = Math.Max(FirstTyphoonRange.StartIndex - 2, 2); firstIdx < FirstTyphoonRange.EndIndex; firstIdx++)
            {
                //首航班不调整
                if (firstIdx == 0)
                {
                    continue;
                }
                //是否存在无法降落的航班
                var firstAirline = first[firstIdx];

                //相同起飞机场的检查
                var FocusAirport = firstAirline.StartAirPort;
                for (int secondIdx = Math.Max(SecondTyphonnRange.StartIndex - 2, 2); secondIdx < SecondTyphonnRange.EndIndex; secondIdx++)
                {
                    //首航班不调整
                    if (secondIdx == 0)
                    {
                        continue;
                    }
                    var secondAirline = second[secondIdx];
                    if (secondAirline.StartAirPort != FocusAirport)
                    {
                        continue;
                    }
                    //联程不能换飞机(但是可以同时换两个)
                    if ((first[firstIdx].ComboAirline != null && !first[firstIdx].IsFirstCombinedVoyage) ||
                        second[secondIdx].ComboAirline != null && !second[secondIdx].IsFirstCombinedVoyage)
                    {
                        continue;
                    }

                    var FirstAirlineListClone  = Utility.DeepCopy(first);
                    var SecondAirlineListClone = Utility.DeepCopy(second);
                    //时间测试(起飞关系不能乱,等于也不可以,防止前后航班关系错乱)
                    var TakeoffAfterThisTime = SecondAirlineListClone[secondIdx - 1].ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    var AddTime = TakeoffAfterThisTime.Subtract(FirstAirlineListClone[firstIdx].ModifiedStartTime);
                    if (AddTime.TotalMinutes > 0)
                    {
                        //尝试是否能够将first整体后移
                        for (int i = firstIdx; i < first.Count; i++)
                        {
                            FirstAirlineListClone[i].ModifiedStartTime += AddTime;
                        }
                    }

                    TakeoffAfterThisTime = FirstAirlineListClone[firstIdx - 1].ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    AddTime = TakeoffAfterThisTime.Subtract(SecondAirlineListClone[secondIdx].ModifiedStartTime);
                    if (AddTime.TotalMinutes > 0)
                    {
                        //尝试是否能够将first整体后移
                        for (int i = secondIdx; i < second.Count; i++)
                        {
                            SecondAirlineListClone[i].ModifiedStartTime += AddTime;
                        }
                    }
                    if (!Exchange(FirstAirlineListClone, firstIdx, SecondAirlineListClone, secondIdx))
                    {
                        continue;
                    }
                    var FirstForTest  = new List <Airline>();
                    var SecondForTest = new List <Airline>();
                    foreach (var air in FirstAirlineListClone)
                    {
                        if (air.ModifiedPlaneID == firstPlaneId)
                        {
                            FirstForTest.Add(air);
                        }
                        else
                        {
                            SecondForTest.Add(air);
                        }
                    }
                    foreach (var air in SecondAirlineListClone)
                    {
                        if (air.ModifiedPlaneID == firstPlaneId)
                        {
                            FirstForTest.Add(air);
                        }
                        else
                        {
                            SecondForTest.Add(air);
                        }
                    }
                    //测试一下交换后分数
                    FirstForTest.Sort((x, y) => { return(x.ModifiedStartTime.CompareTo(y.ModifiedStartTime)); });
                    SecondForTest.Sort((x, y) => { return(x.ModifiedStartTime.CompareTo(y.ModifiedStartTime)); });
                    var FirstScoreAfter = Solution.FixAirline(FirstForTest, true).Score;
                    if (FirstScoreAfter == double.MaxValue)
                    {
                        continue;
                    }
                    var SecondScoreAfter = Solution.FixAirline(SecondForTest, true).Score;
                    if (SecondScoreAfter == double.MaxValue)
                    {
                        continue;
                    }
                    var TotalScoreAfter = FirstScoreAfter + SecondScoreAfter;
                    var Minius          = Math.Round(TotalScoreAfter, 0) - Math.Round(TotalScore, 0);
                    Rtn = new ExchangeRecord()
                    {
                        firstIndex    = firstIdx,
                        secondIndex   = secondIdx,
                        firstPlaneId  = firstPlaneId,
                        secondPlaneId = secondPlandId,
                        firstScore    = FirstScoreAfter,
                        secondScore   = SecondScoreAfter,
                        DiffScore     = Minius,
                    };
                    return(Rtn);
                }
            }
            return(Rtn);
        }