综合算法04—非排序换乘算法

一、算法描述

问题描述:已知站点,线路,线路-站点数据,求指定点之间的:

1、直达线路
2、一次换乘线路
3、两次换乘线路

模块1:直达线路算法
Step1:S为过起点A的线路集合,T为过终点B的线路集合;
Step2:ZDXL为直达线路,ZDXL=S∩T;ZDD为在直达线路上的点
Step3:若某条线路上起点在终点后面,则该线路不是直达线路(区分上下行)

模块2:一次换乘线路算法
Step1:与起点直达的点的集合zhan_A,与终点直达的点的集合zhan_B;
Step2:剔除在起讫点直达线路上的点ZDD_AB;
Step4:一次换乘点HCD_1ci=zhan_A∩zhan_B;
Step5:针对每一个换乘点i,再利用模块1的直达算法求得起点到每一个换乘点的直达线路;同理求得换乘点到终点的直达线路;则一次换乘线路为两段直达线路的组合。

模块3:二次换乘线路算法
Step1:找到与A直达的点的集合Z2,S2为过Z2的线路;
Step2:求与Z2直达的点集合并剔除直达点和一次换乘点记为zhan_2_A;
Step3:二次换乘点HCD_2ci=zhan_2_A∩zhan_B;
Step4:起点不变,以HCD_2ci为终点,调用一次换乘算法求得一次换乘点HCD_1,则起点、一次换乘点、二次换乘点、终点被确定;
Step5:分段,第一段:【起点,一次换乘点】;第二段:【一次换乘点,二次换乘点】,第三段:【二次换乘点,终点】;
Step6:分别对三段调用直达算法求得各段的直达线路,则二次换乘方案为三段直达线路的组合。

总算法:
Step1:数据准备,输入或调用编辑好的路网数据,输入起点和终点;
Step2:调用直达函数,输出直达方案(不排序);
Step3:调用一次换乘函数,输出一次换乘方案(不排序);
Step4:调用二次换乘函数,输出二次换乘方案(不排序)。

补充说明:
如有换乘路径,但换乘点在直达线路上,算法认为没有必要换乘,即舍去该换乘方案,然而有时候舍去的方案可能费用更省,在此不再深究。
例如:从v2到v9有很多条路径,但由于其他路径的换乘点在直达线路L1或L4上,故不管其路径费用是多少都舍弃其他方案。

二、算法程序

使用说明:将以下代码分别保存为m文件放在同一个目录下,注意名称不能写错,修改案例请打开luwangshuju.m,运行程序请打开huanchengsuanfa.m。

1. fuhaoshuoming.m

fprintf('=======================================================================\n');
fprintf('                   《换乘方案算法——不对方案排序》\n');
fprintf('运行环境:MATLAB 8.3.0.532 \n');
fprintf('作者信息:兰州交通大学  刘志祥   QQ:531548824\n');
fprintf('说明:本程序用于在已知路网数据时,通过输入起讫点求直达、一次、二次换乘方案。\n')
fprintf('=======================================================================\n\n');
%《路网数据符号》
% luwangshuju-路网数据,包括站数据(点编号),线数据(线编号),站—线数据(线路包含的站点)
% A-起点
% B-终点
% zhan-站集合,本程序中站点以V开头编号
% xian-线集合,可理解为公交车名称,如k102等
% zhan_xian-线与站的关系,表示线路上有哪些站点

%《数据处理符号》
% zhan_xian_01-线与站的01矩阵,行表示线,列表示站,0表示不在该线,1表示在该线上
% xian_zhan_01-站与线的01矩阵,行表示站,列表示线,0表示线不经过站,1表示经过,与zhan_xian_01互为转置矩阵

%《直达算法符号》
% S-经过起点的所有线路集合
% T-经过终点的所有线路集合
% ZDXL-直达线路,是S与T的交集
% ZDD-直达线路上的点

%《一次换乘算法符号》
% D_A-与A直达的点的集合(矩阵的行是线,列是站,表示线路是否经过该站点)
% D_B-与B直达的点的集合(同上)
% Z2-为与A直达的点
% X2-为Z2所在的线路
% S2-过与A直达的点的线路
% E2-把与A直达的点zhan_A看作起点,与该点直达的点的集合,即S2上的点
% zhan_A-与起点A直达的点的集合(剔除直达点后)
% xian_A-表示zhan_A所在的线路集合(一一对应)
% zhan_B-与终点B直达的点的集合(剔除起讫点直达线路点后的)
% xian_B-表示zhan_B所在的线路集合(一一对应)
% HCX_1ci_qianmian-一次换乘的前段线路
% HCX_1ci_houmian-一次换乘的末段线路
% HCD_1ci-一次换乘点
% HCX_1ci-一次换乘线集合(第1行表示前段线路,第2行表示末段线路)

%《二次换乘算法符号》
% Point-二次换乘4个关键点【起点 换乘点1 换乘点2 终点】
% HCD_1-换乘点1
% HCD_2-换乘点2
% HCX_1-前段线路【起点-换乘点1】
% HCX_2-中段线路【换乘点1-换乘点2】
% HCX_3-末段线路【换乘点2-终点】

%《总换乘算法符号》
% ZDX_AB-起讫点间的直达线
% ZDD_AB-起讫点间的直达点
% HCX_1ci_AB-起讫点直接的一次换乘线
% HCD_1ci_AB-起讫点直接的一次换乘点
% HCX_2ci_AB-起讫点直接的二次换乘线
% HCD_2ci_AB-起讫点直接的一次换乘点

%其他符号见程序内注释


2. luwangshuju.m

%==========================================================================
% 路网数据
% 运行可得基础路网数据
% 主要计算结果:【输入起讫点 得到路网的站-线-权数据 】
%==========================================================================
%% 输入始发点和目的地
qidian=2;
zhongdian=9;
A=qidian;
B=zhongdian;
%% 数据for换乘算法
% %例1
% %==========================================================================
% zhan=[1 2 3 4 5 6 7 8 9];                                                   %站数据
% xian={1 2 3 4 5 6};                                                         %线路数据
% xian_zhan={[1 2 4 6],[1 3 5 7 8],[9 2 5 6],[6 4 2 1],[8 7 5 3 1],[6 5 2 9]};%线路包含哪些站
% %==========================================================================

%例2
%==========================================================================
zhan=[1 2 3 4 5 6 7 8 9 10 11 12 13];                                       %站数据
xian=[1 2 3 4 5 6];                                                         %线路数据
xian_zhan={[1 2 3 6 9 8 7 4],[10 4 5 6 11],[12 2 5 8 13],[4 7 8 9 6 3 2 1],...
    [11 6 5 4 10],[13 8 5 2 12]};              
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的地铁管理系统的 C 语言代码,包含了最短路径换乘的功能: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 1000 #define INF 0x3f3f3f3f int graph[MAX][MAX]; // 存储地铁线路图 int n; // 地铁站点数量 /* Dijkstra算法求最短路径 参数: start: 起点 end: 终点 path[]: 存储最短路径 返回值: 最短路径长度 */ int dijkstra(int start, int end, int path[]) { int dist[MAX]; // 存储起点到各点的最短距离 int visited[MAX]; // 存储该点是否已被访问 int pre[MAX]; // 存储最短路径上的前一个点 int i, j, k, min; // 初始化 for (i = 1; i <= n; i++) { dist[i] = graph[start][i]; visited[i] = 0; // 未被访问 if (dist[i] == INF) pre[i] = -1; // 无法到达 else pre[i] = start; // 起点到该点的前一个点为起点 } dist[start] = 0; visited[start] = 1; // 计算最短路径 for (i = 2; i <= n; i++) { min = INF; for (j = 1; j <= n; j++) { if (!visited[j] && dist[j] < min) { min = dist[j]; k = j; } } visited[k] = 1; for (j = 1; j <= n; j++) { if (!visited[j] && dist[k] + graph[k][j] < dist[j]) { dist[j] = dist[k] + graph[k][j]; pre[j] = k; } } } // 构建最短路径 j = end; i = 0; while (j != start) { path[i++] = j; j = pre[j]; } path[i] = start; // 翻转路径 for (j = 0; j <= i / 2; j++) { k = path[j]; path[j] = path[i - j]; path[i - j] = k; } return dist[end]; } /* 换乘算法 参数: start: 起点 end: 终点 path[]: 存储最短路径 返回值: 最短路径长度 */ int transfer(int start, int end, int path[]) { int i, j, k, min; int dist[MAX]; // 存储起点到各点的最短距离 int visited[MAX]; // 存储该点是否已被访问 int pre[MAX]; // 存储最短路径上的前一个点 int line[MAX]; // 存储从起点到各点的最短路径所经过的线路 // 初始化 for (i = 1; i <= n; i++) { dist[i] = graph[start][i]; visited[i] = 0; // 未被访问 if (dist[i] == INF) pre[i] = -1; // 无法到达 else pre[i] = start; // 起点到该点的前一个点为起点 line[i] = -1; } dist[start] = 0; visited[start] = 1; // 计算最短路径 for (i = 2; i <= n; i++) { min = INF; for (j = 1; j <= n; j++) { if (!visited[j] && dist[j] < min) { min = dist[j]; k = j; } } visited[k] = 1; for (j = 1; j <= n; j++) { if (!visited[j] && dist[k] + graph[k][j] < dist[j]) { dist[j] = dist[k] + graph[k][j]; pre[j] = k; line[j] = graph[k][j]; // 记录经过的线路 } else if (!visited[j] && dist[k] + graph[k][j] == dist[j] && line[j] > 0) { line[j] += graph[k][j]; // 更新线路权值 } } } // 构建最短路径 j = end; i = 0; while (j != start) { path[i++] = j; j = pre[j]; } path[i] = start; // 翻转路径 for (j = 0; j <= i / 2; j++) { k = path[j]; path[j] = path[i - j]; path[i - j] = k; } // 输出换乘信息 printf("从%s到%s的最短路线为:\n", start, end); int curLine = -1; for (i = 0; i < n - 1; i++) { if (line[path[i + 1]] != line[path[i]]) { printf("在%s站换乘%s线路\n", path[i], line[path[i + 1]]); curLine = line[path[i + 1]]; } } printf("到达%s站\n", end); return dist[end]; } int main() { // 读入地铁线路图 scanf("%d", &n); memset(graph, INF, sizeof(graph)); int i, j, k, m; for (i = 1; i <= n; i++) { scanf("%d", &m); for (j = 0; j < m; j++) { scanf("%d", &k); if (j > 0) { graph[k][i] = graph[i][k] = 1; // 相邻站点距离为1 } } } // 读入起点和终点 int start, end; scanf("%d %d", &start, &end); // 求最短路径 int path[MAX]; int dist = dijkstra(start, end, path); // 输出结果 printf("从%s到%s的最短路线为:\n", start, end); for (i = 0; i < n; i++) { if (i == 0) printf("%s", path[i]); else printf("->%s", path[i]); } printf("\n距离为%d\n", dist); // 换乘 transfer(start, end, path); return 0; } ``` 需要注意的是,这只是一个简单的示例代码,实际情况可能更加复杂,需要根据具体情况进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值