郑州地铁收费 计应192西—第一组—王晶宇

计应192西—第一组—王晶宇

计划:每次坐地铁,我们都是凭肉眼去得出我们心中最佳的换乘方案,但是,如果对于线路较少的城市来说,这个方法是最快的,但是如果对于线路较多的城市,例如北京或者上海,十几条线路交叉穿梭,我们可能看到都晕了,怎么坐才是时间最短路程最短的,我们要算出来不是不可以但是很麻烦,我们也可以想一想,百度地图的地铁换乘算法是怎么实现的,于是,闲着没事,我就想写一个通用的地铁换乘查询程序,想用计算机运算得出科学一点的换乘方案供自己参考,假设先不考虑站点间的距离差异,我们以乘坐站点数最少为最优方案

需求分析:作为一位每天要乘坐地铁的富二代,我希望通过这个软件可以计算我每次坐地铁路线换乘方案,以便我省心

开发思路:

1、采用xml存储站点数据,

2、代码中使用集合初始化线路数据

3、分多种情况进行处理,核心代码

 

代码:

 /// <summary>  

2         /// 获取地铁乘车信息

  3         /// </summary>

  4         /// <param name="depStation">出发站</param> 

 5         /// <param name="destStation">到达站</param>  

6         /// <param name="city">所在城市</param> 

 7         /// <returns>返回各种换乘方案</returns> 

 8         public static List<QueryResult> GetRideSubwayInfo(string depStation, string destStation, CityEnum city) 

 9         {

 10             InitSubwayLine(city);

 11             if (string.IsNullOrWhiteSpace(depStation) || string.IsNullOrWhiteSpace(destStation)

 12                 || !AllSubwayLines.Exists(x => x.Stations.Exists(y => y.Name.Equals(depStation)))

 13                 || !AllSubwayLines.Exists(x => x.Stations.Exists(y => y.Name.Equals(destStation)))) 14                 return null;//出发站或到达站在线路上不存在!

 15

  16             //各种换乘提示

 17             //同一条线路

 18             var msg_oneline = "在{0}【{1}】上车,经过{2}站到达目的站【{3}】。\r\n具体线路为:\r\n(出发){4}(到达)\r\n总搭乘站点数:{5}\r\n";

 19             //换乘1次

 20             var msg_transOnce = "在{0}【{1}】上车,经过{2}站在【{3}】下车,换乘{4},经过{5}站到达目的站【{6}】。\r\n具体线路为:\r\n(出发){7}(此处换乘{4})-->{8}(到达)\r\n总搭乘站点数:{9}\r\n";

 21             //换乘2次

 22             var msg_transTwice = "在{0}【{1}】上车,经过{2}站在【{3}】下车,换乘{4},经过{5}站在【{6}】下车,换乘{7},经过{8}站到达目的站【{9}】。\r\n具体线路为:\r\n(出发){10}(此处换乘{4})-->{11}(此处换乘{7})-->{12}(到达)\r\n总搭乘站点数:{13}\r\n";

 23             //换乘3次 

24             var msg_transThreetimes = "在{0}【{1}】上车,经过{2}站在【{3}】下车,换乘{4},经过{5}站在【{6}】下车,换乘{7},经过{8}站在【{9}】下车,换乘{10},经过{11}站到达目的站【{12}】。" 

25                 + "\r\n具体线路为:\r\n(出发){13}(此处换乘{4})-->{14}(此处换乘{7})-->{15}(此处换乘{10})-->{16}(到达)\r\n总搭乘站点数:{17}\r\n"; 

26             //换乘4次

 27             var msg_transFourtimes = "在{0}【{1}】上车,经过{2}站在【{3}】下车,换乘{4},经过{5}站在【{6}】下车,换乘{7},经过{8}站在【{9}】下车,换乘{10},经过{11}站在【{12}】下车,换乘{13},经过{14}站到达目的站【{15}】。" 

28                 + "\r\n具体线路为:\r\n(出发){16}(此处换乘{4})-->{17}(此处换乘{7})-->{18}(此处换乘{10})-->{19}(此处换乘{13})-->{20}(到达)\r\n总搭乘站点数:{21}\r\n";

 29 

 30             //保存各种换乘方案 

31             var result = new List<QueryResult>(); 

32             //第一步:先查找始发站和到达站在哪一条线路 

33             var afterDepLines = GetAcrossLines(depStation);

 34             var afterDestLines = GetAcrossLines(destStation);

 35             //根据同一条线和不同线路展开分析

 36             if (IsSameLine(depStation, destStation))

 37             { 

38                 #region 同一条线路

 39                 var commLines = afterDepLines.Where(x => afterDestLines.Select(y => y.No).Contains(x.No)).ToList();

 40                 //判断线路是否相同,相同直接计算站点距离

 41                 var depIndex = GetIndexOnLine(depStation, commLines.First());

 42                 var destIndex = GetIndexOnLine(destStation, commLines.First());

 43                 var crossStations = commLines.First().Stations.Between(depIndex, destIndex).Select(x => x.Name).ToList(); 

44                 var range = crossStations.Count - 1;

 45                 if (depIndex > destIndex) crossStations.Reverse();

 46                 var rs = msg_oneline.FormatTo(commLines.First().ToString(), depStation, range, destStation, 

47                          crossStations.ToJoinString(), range); 

48                 result.Add(new QueryResult() { Description = rs, Range = range }); 

49                 #endregion 

50             } 

51             else 

52             { 

53                 #region 不同线路 

54                 if (!IsTransferStation(depStation) && !IsTransferStation(destStation))//如果始发站和终点站都不是换乘站,则表示始发站和到达站都是只有一条线路通过

 55                 { 

56                     if (afterDepLines.First().IsIntersect(afterDestLines.First()))

 57                     { 

58                         #region 如果两条线路交叉,一定有换乘站点 

59                         var clist = GetAcrossStations(afterDepLines.First(), afterDestLines.First()).Select(x => x.Name).ToList(); 

60                         var i = GetIndexOnLine(depStation, afterDepLines.First());

 61                         var j = GetIndexOnLine(clist.First(), afterDepLines.First());

 62                         var k = GetIndexOnLine(destStation, afterDestLines.First()); 

63                         var l = GetIndexOnLine(clist.First(), afterDestLines.First()); 

64                         var coss1 = afterDepLines.First().Stations.Between(i, j).Select(x => x.Name).ToList(); 

65                         var coss2 = afterDestLines.First().Stations.Between(k, l).Select(x => x.Name).ToList();

 66                         if (i > j) coss1.Reverse();

 67                         if (k < l) coss2.Reverse(); 

68                         var rang1 = coss1.Count - 1; 

69                         var rang2 = coss2.Count - 1; 

70                         var h = rang1 + rang2; //站点数

 71                         var rs = msg_transOnce.FormatTo(afterDepLines.First().ToString(), depStation, rang1, clist.First(), 

72                             afterDestLines.First().ToString(), rang2, destStation, 

73                             coss1.ToJoinString(), coss2.Where(x => x != clist.First()).ToJoinString(), h); 

74                         result.Add(new QueryResult() 

75                         {

 76                             Description = rs, 

77                             Range = h,

 78                             TransferStations = new List<string>() { clist.First() }, 

79                             TransferTimes = 1

 80                         });

 81                         #endregion 

82                     }

 83                     else

 84                     {

 85                         #region 不交叉,需要通过第三条线路换乘,即多次换乘

 86                         var depSta = GetStation(depStation);

 87                         var destSta = GetStation(destStation); 

88                         //找出两条线路的可换乘站点,找出可换乘相同线路的站点 

89                         var trans1 = afterDepLines.First().GetTransStations(); 

90                         var trans2 = afterDestLines.First().GetTransStations(); 

91                         var trans3 = new List<Station>(); 

92                         var trans4 = new List<Station>(); 

93                         var expets = trans1.Join(trans2, x => x.TransferNo, y => y.TransferNo, (x, y) =>

 94                         { 

95                             trans3.Add(x); 

96                             trans4.Add(y); 

97                             return x.Name + "---" + y.Name;

 98                         }).ToList(); 

99                         if (expets.Any())

100                         {

101                             #region 两次换乘

102                             //trans3.Count和trans4.Count必定相等

103                             //计算最短距离,列出所有换乘方案

104                             for (var i = 0; i < trans3.Count; i++)

105                             {

106                                 var tranLine = GetLine(trans3[i].TransferNo);

107                                 //获取这两个站点在此线路的索引                  

108                                 var ix1 = depSta.Index;

109                                 var ix2 = destSta.Index;

110                                 var iix1 = GetIndexOnLine(trans3[i].Name, depSta.LineNo);

111                                 var iix2 = GetIndexOnLine(trans4[i].Name, destSta.LineNo);

112                                 var tx1 = GetIndexOnLine(trans3[i].Name, tranLine);

113                                 var tx2 = GetIndexOnLine(trans4[i].Name, tranLine);

114 115                                 var depRange = afterDepLines.First().Stations.Between(ix1, iix1).Select(x => x.Name).ToList();

116                                 var destRange = afterDestLines.First().Stations.Between(ix2, iix2).Select(x => x.Name).ToList();

117                                 var transRange = tranLine.Stations.Between(tx1, tx2).Select(x => x.Name).ToList();

118                                 if (ix1 > iix1) depRange.Reverse();

119                                 if (ix2 < iix2) destRange.Reverse();

120                                 if (tx1 > tx2) transRange.Reverse();

121                                 var r1 = depRange.Count - 1;

122                                 var r2 = destRange.Count - 1;

123                                 var r3 = transRange.Count - 1;

124                                 var r = r1 + r2 + r3;

125                                 var rs = msg_transTwice.FormatTo(afterDepLines.First().ToString(), depStation, r1,

126                                     trans3[i].Name,

127                                     tranLine.ToString(), r3, trans4[i].Name, afterDestLines.First().ToString(), r2,

128                                     destStation, depRange.ToJoinString(),

129                                         transRange.Where(x => !x.IsSame(trans3[i].Name) && !x.IsSame(trans4[i].Name)).ToJoinString(),

130                                      destRange.ToJoinString(), r);131                                 result.Add(new QueryResult()132                                 {

133                                     Description = rs,134                                     Range = r,

135                                     TransferTimes = 2

,136                                     TransferStations = new List<string>() { trans3[i].Name, trans4[i].Name }

137                                 });

138                             }

139                             #endregion

140                         }

141                         #region 查找3次以上换乘的可能结果,寻求最短距离

142                         var trlines1 = afterDepLines.First().TransferLines.Select(GetLine).ToList();

143                         var trlines2 = afterDestLines.First().TransferLines.Select(GetLine).ToList();

144                         var destss = new List<Station>();

145 146                         #region 换乘3次

147                         foreach (var depline in trlines1)

148                         {

149                             foreach (var destline in trlines2)150                             {

151                                 var ss = destline.GetAcrossStations(depline);

152                                 if (!ss.Any()) continue; //3次换乘

153                                 var slist1 = afterDepLines.First().GetAcrossStations(depline);

154                                 if (!slist1.Any()) continue;

155                                 var s1 = slist1.GetClosestStation(depSta.Name);

156                                 var s1_ix1 = depSta.Index;

157                                 var s1_ix2 = s1.Index;

158                                 var s1_range =

159                                     afterDepLines.First()

160                                         .Stations.Between(s1_ix1, s1_ix2)

161                                         .Select(x => x.Name)

162                                         .ToList();163                                 var s1_h = s1_range.Count - 1;

164                                 if (s1_ix1 > s1_ix2) s1_range.Reverse();

165 166                                 var s2_ix1 = GetIndexOnLine(s1.Name, depline);

167                                 var s2_ix2 = GetIndexOnLine(ss.First().Name, depline);

168                                 var s2_range = depline.Stations.Between(s2_ix1, s2_ix2).Select(x => x.Name).ToList();

169                                 var s2_h = s2_range.Count - 1;

170                                 if (s2_ix1 > s2_ix2) s2_range.Reverse();

171 172                                 var slist3 = destline.GetAcrossStations(afterDestLines.First());

173                                 if (!slist3.Any()) continue;

174                                 var s3 = slist3.GetClosestStation(ss.First().Name);

175                                 var s3_ix1 = s3.Index;

176                                 var s3_ix2 = ss.First().Index;

177                                 var s3_range = destline.Stations.Between(s3_ix1, s3_ix2).Select(x => x.Name).ToList();

178                                 var s3_h = s3_range.Count - 1;

179                                 if (s3_ix1 < s3_ix2) s3_range.Reverse();1

80 181                                 var s4_ix1 = GetIndexOnLine(s3.Name, afterDestLines.First());

182                                 var s4_ix2 = destSta.Index;

183                                 var s4_range =

184                                     afterDestLines.First()

185                                         .Stations.Between(s4_ix1, s4_ix2)

186                                         .Select(x => x.Name)

187                                         .ToList();

188                                 var s4_h = s4_range.Count - 1;

189                                 if (s4_ix1 > s4_ix2) s4_range.Reverse();

190 191                                 var h = s1_h + s2_h + s3_h + s4_h;

192                                 var rs = msg_transThreetimes.FormatTo(afterDepLines.First().ToString(), depStation,

193                                     s1_h, s1.Name,

194                                     depline.ToString(), s2_h, ss.First().Name,

195                                     GetLine(ss.First().LineNo).ToString(), s3_h, s3.Name,

196                                     afterDestLines.First().ToString(), s4_h, destStation, s1_range.ToJoinString(),

197                                     s2_range.Where(x => x != s1.Name).ToJoinString(),

198                                     s3_range.Where(x => x != ss.First().Name).ToJoinString(),

199                                     s4_range.Where(x => x != s3.Name).ToJoinString(), h);

200                                 result.Add(new QueryResult()201                                 {

202                                     Description = rs,203                                     Range = h,

204                                     TransferTimes = 3,

205                                     TransferStations =

206                                         new List<string>()

207                                         {

208                                                         s1.Name,

209                                                         ss.First().Name,

210                                                         s3.Name

211                                         }

212                                 });

213                                 destss.AddRange(ss);

214                             }

215                         }

 

 

测试:

 

 

 

posted @ 2021-04-11 11:44  计应192西一组  阅读(125)  评论(0)    收藏  举报