郑州地铁收费 计应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 }
测试:





浙公网安备 33010602011771号