最近做数学建模模拟赛,遇到一个公交调度的问题,原题给的两个附件,一个是每班公交的线路,另一个是所有教师的居住小区,然后题目要求给出一个既考虑服务质量(接最多的人)又考虑服务成本(走最短的路)的公交路线。
第一眼看这道题立马想到的是整理附件一的公交路线,整理出一个以公交车为行,以站点为列的矩阵,但附件有83辆公交车,我肯定不能手动的去数,根据文件内容格式特点:每个相邻站点之间均用箭头连接,利用Python的文件处理,最后整理出只包含线路的文本。
接着利用Java的文件处理以及Set最终整理出不重复的1146个站点,再根据公交线路信息,得到站点的邻接矩阵。
而原题就变成了在这1146个站点中选取居民最集中的20个点,找出一条经过这些站点的从起点到终点的最短路径。
提取特征文字的部分就不贴代码了,过特定点的最短路径问题,刚开始查网上代码,发现没有代码,只有算法,迫于做题需要就自己实现了一下。
起点->中间点集->终点
将中间点集形成全排列,分别计算起点到中间点集的第一个点的最短距离,中间点集相邻两点的间的最短距离,中间点集最后一个点到终点的最短距离。
算法参考链接:https://wenku.baidu.com/view/ca2b856c83d049649a665826.html
//实现最短路径的主方法
private static int mainMethod() {
int path = MAX;
int temp;
int line = -1;
//将中间结点形成全排列,arrays[][]存放全排列数组
for(int i = 0; i < count; i++) {
midPath = PathMidNode(i);
temp = Dijistra(Vbegin,arrays[i][0]) + midPath + Dijistra(arrays[i][point_num-1],Vend);
if(temp < path) {
path = temp;//path为最终的最短距离
line = i; //记录路径最短的排列
}
}
System.out.println("min:" + path);
return line;
}
//求中间结点之间近距离和路径
public static int PathMidNode(int i) {
int dist = 0;
int dis = 0;
for(int j = 0; j < point_num-1; j++) {
//System.out.println(arrays[i][j]+","+arrays[i][j+1]);
if(G[arrays[i][j]][arrays[i][j+1]] == 1) { //若两站相邻则两站之间最短距离为1
System.out.println(arrays[i][j]+","+arrays[i][j+1]);
dis = 1;
}
else
dis = Dijistra(arrays[i][j],arrays[i][j+1]); //两站之间不相邻,则通过Dijistra计算最短路径
dist += dis;
//System.out.println("dist:" + dist);
}
return dist;
}
//计算u,v之间的最短路径,u为终点,vs为起点
public static int Dijistra(int vs,int u) {
int length = 0;
int NUM = 1146;
// System.out.println(NUM);
// 前驱节点数组
int[] prenode = new int[NUM];
// 最短距离数组
int[] mindist = new int[NUM];
// 该节点是否已经找到最短路径
boolean[] find = new boolean[NUM];
int vnear = 0;
for (int i = 0; i < NUM; i++) {
prenode[i] = i;
mindist[i] =
G[vs][i];
find[i] = false;
//System.out.println(G[vs][i]);
}
find[vs] = true;
for (int v = 1; v < NUM; v++) {
// 每次循环求得距离vs最近的节点vnear和最短距离min
int min = MAX;
for (int j = 0; j < NUM; j++) {
if (!find[j] && mindist[j] < min) {
min = mindist[j];
vnear = j;
}
}
find[vnear] = true;
// 根据vnear修正vs到其他所有节点的前驱节点及距离
for (int k = 0; k < 1146; k++) {
if (!find[k] &&
(min + G[vnear][k]) < mindist[k]) {
prenode[k] = vnear;
mindist[k] = min + G[vnear][k];
}
}
}
return mindist[u];
}