用Dijstra算法求解2007高教社杯全国大学生数学建模B题

B题:乘公交,看奥运

 

    我国人民翘首企盼的第29届奥运会明年8月将在北京举行,届时有大量观众到现场观看奥运比赛,其中大部分人将会乘坐公共交通工具(简称公交,包括公汽、地铁等)出行。这些年来,城市的公交系统有了很大发展,北京市的公交线路已达800条以上,使得公众的出行更加通畅、便利,但同时也面临多条线路的选择问题。针对市场需求,某公司准备研制开发一个解决公交线路选择问题的自主查询计算机系统。

为了设计这样一个系统,其核心是线路选择的模型与算法,应该从实际情况出发考虑,满足查询者的各种不同需求。请你们解决如下问题:

1、仅考虑公汽线路,给出任意两公汽站点之间线路选择问题的一般数学模型与算法。并根据附录数据,利用你们的模型与算法,求出以下6对起始站→终到站之间的最佳路线(要有清晰的评价说明)。

      (1)、S3359→S1828    (2)、S1557→S0481  (3)、S0971→S0485

(4)、S0008→S0073   (5)、S0148→S0485   (6)、S0087→S3676

2、同时考虑公汽与地铁线路,解决以上问题。

3、假设又知道所有站点之间的步行时间,请你给出任意两站点之间线路选择问题的数学模型。

 

【附录1】基本参数设定

相邻公汽站平均行驶时间(包括停站时间): 3分钟

相邻地铁站平均行驶时间(包括停站时间): 2.5分钟

公汽换乘公汽平均耗时:        5分钟(其中步行时间2分钟)

地铁换乘地铁平均耗时:        4分钟(其中步行时间2分钟)

地铁换乘公汽平均耗时:        7分钟(其中步行时间4分钟)

公汽换乘地铁平均耗时:        6分钟(其中步行时间4分钟)

公汽票价:分为单一票价与分段计价两种,标记于线路后;其中分段计价的票价为:0~20站:1元;21~40站:2元;40站以上:3元

地铁票价:3元(无论地铁线路间是否换乘)

注:以上参数均为简化问题而作的假设,未必与实际数据完全吻合。

 

【附录2】公交线路及相关信息 (见数据文件B2007data.rar)

====================================================================================================================

本文用Dijstra算法分别根据时间最少和费用最少两种方式进行了求解,由于本人数据基础不好,所以没有数学模型和符号之类的东东,只有算法程序。下面是对题2的答案,题1就不单独解答了。题3后面再说。

(1)、S3359→S1828

输入出发站:
S3359
输入终点站:
S1828
选择优先选项:
1. 时间少
2. 花钱少
1
开始搜索...2017-07-25 15:19:32.684
搜索结束...2017-07-25 15:19:33.262
在S3359乘坐[L015上行]在S1327乘坐[L021上行, L026上行, L081下行, L123下行, L201上行, L262上行, L293上行, L300下行, L328上行, L354下行]在S0525乘坐[L103上行]在S0073乘坐[L480下行]在S2704乘坐[L027环行]在S1784乘坐[L167下行, L217下行]到达目的站S1828
总共用时:67.0分钟,累计票价:6元

输入出发站:
S3359
输入终点站:
S1828
选择优先选项:
1. 时间少
2. 花钱少
2
开始搜索...2017-07-25 15:21:16.543
搜索结束...2017-07-25 15:21:23.207
在S3359乘坐[L015下行, L123上行, L132下行, L352下行, L366上行, L436上行, L474下行]在S2903乘坐[L201上行]在S1790乘坐[L041上行, L167下行, L217下行]到达目的站S1828
总共用时:73.0分钟,累计票价:3元


(2)、S1557→S0481

输入出发站:
S1557
输入终点站:
S0481
选择优先选项:
1. 时间少
2. 花钱少
1
开始搜索...2017-07-25 15:24:48.177
搜索结束...2017-07-25 15:24:48.933
在S1557乘坐[L084下行, L363下行, L457下行]在S1919乘坐[L189下行]在S3186乘坐[L007下行, L091上行, L132上行, L242上行, L256上行, L264上行, L290环行, L317上行, L386上行, L387上行, L395上行, L414下行, L417上行, L460下行, L511下行]在S0903乘坐[L254上行, L312下行, L447上行, L460下行, L514环行, L516上行]到达目的站S0481
总共用时:99.0分钟,累计票价:4元

输入出发站:
S1557
输入终点站:
S0481
选择优先选项:
1. 时间少
2. 花钱少
2
开始搜索...2017-07-25 15:26:42.917
搜索结束...2017-07-25 15:26:48.508
在S1557乘坐[L084下行, L363下行]在S1919乘坐[L189下行]在S3186乘坐[L460下行]到达目的站S0481
总共用时:106.0分钟,累计票价:3元

(3)、S0971→S0485

输入出发站:
S0971
输入终点站:
S0485
选择优先选项:
1. 时间少
2. 花钱少
1
开始搜索...2017-07-25 15:28:21.872
搜索结束...2017-07-25 15:28:22.661
在S0971乘坐[L013上行, L024下行, L094上行, L119下行, L160下行, L263下行, L310上行]在S0567乘坐[步行]在D01乘坐[T1上行]在D21乘坐[步行]在S0466乘坐[L051上行, L450下行]到达目的站S0485
总共用时:104.0分钟,累计票价:5元

输入出发站:
S0971
输入终点站:
S0485
选择优先选项:
1. 时间少
2. 花钱少
2
开始搜索...2017-07-25 15:28:53.983
搜索结束...2017-07-25 15:28:59.34
在S0971乘坐[L013上行, L024下行, L094上行, L119下行, L263下行]在S1609乘坐[L140下行]在S2654乘坐[L469上行, L417下行]到达目的站S0485
总共用时:106.0分钟,累计票价:3元

==================================================================================================================

答案就写到这了吧,时间有限。下面来说一下算法实现。在算法实现之前其实还需要对数据进行分析处理,以下是我对数据的分析:

1. 对于一个公交、地铁线路,除了换线线路外,分别建立两条单独的线路,比如L001路公交,我会建立2个公交线路,即L001上行和L001下线。换线线路只有一条。

2. 对于公交和地铁的转乘。虽然数据给出了公交-地铁转乘站点,但我们不能把这些转乘点当成一个站点来处理,因此我认为地加入了步行线路:公交站到地铁站和地铁站到公交站的步行线路。在我的数据里面步行下路是以L901开始的。对于步行线路,只有步行时间,没有任何费用。而且在我的假设里面,是可以从一个公交站经过地铁站步行到另一个公交站的。现在来说说问题3,其实我们是可以用这种方法来解决的,但是一点需要加入时间限制(比如步行时间不能超过多少分钟)不然以费用少优先时,那么给出的线路就会只有步行了。

3. 为了编程方便,我的源数据里面对地铁线路和车站做了映射,即地铁T1/T2成了L700和L701,同理D01站成了S9001。


在下面介绍具体算法前,我再程序里面建立了2个HashSet,一个用来保存线路,一个用来保存站点。


==============================================================================================================================

现在来说说怎么用Dijstra算法来处理时间优先线路选择。

1. 将出发站加入已经找到的站点的集合【为了方便,简称集合A】

2. 找到所有经过出发站的公交地铁线路,然后对于每一条线路找到出发站的下一站,并计算好从出发站到这站的时间,当前线路累计经过的站数,车票价格(车票价格可能会依赖于累计站数)。计算好后,需要到候选站点集合【集合B】里面查找该站点是不是已经存在了,如果存在则按照时间(优先),票价(次之)进行比较,如果该站点代价小,则替换掉原站点,若比较结果一样,则将此线路信息加入原来存在的站点线路里面去,表示经过此线路到底站点所花的代价是一样的。如果在集合B里面不存在,则加入集合B。

3. 当找完所有出发站点的下一站之后,需要对集合B根据时间,票价的顺序进行排序,找到代价最小的那个站点,这个站点就是离出发站点时间最少,票价最少的那个点(或之一)。将这个站点从集合B中移除。

4. 将上一步找到的站点当成出发站点,继续循环上面的步骤,知道该站点是目的站点结束。


说完了时间优先线路选择,下面来说说票价优先。时间优先我们每一次找的是上一次找到的站点的下一站点,这是因为时间是根据站点累加的,下一个站点是要比下2个,3个站所话的时间少的。但是票价却不是根据站点累加的,从题目中可以看到有个线路票价是固定的,有的则是按累计站数收费的。所以我们在构造候选集合【集合B】时,我们需要把所有经过出发点直达的所有站点找出来并计算他们说话的时间,累计站数,和票价。注意一点,为什么是直达呢,这是因为直达所产生的费用是<=换乘产生的费用的。具体步骤为:

1. 将出发站加入已经找到的站点的集合【为了方便,简称集合A】

2. 找到所有经过出发站的公交地铁线路,然后对于每一条线路找到并计算好出发站后面所有站点的时间累计站数和车票价格,然后加入集合B中。

3. 当找完所有出发站点的线路之后,需要对集合B根据票价,时间的顺序进行排序,找到代价最小的那个站点,这个站点就是离出发站点票价最少时间最短的那个点(或之一)。将这个站点从集合B中移除。

4. 将上一步找到的站点当成换乘点,继续循环上面的步骤,知道该站点是目的站点结束。


最后附上原数据和程序代码。

http://www.mcm.edu.cn/html_cn/node/a6b7310adbb9eac56152a6815a759986.html

源代码点击打开链接

你可能感兴趣的:(用Dijstra算法求解2007高教社杯全国大学生数学建模B题)