过特定点的最短路径(贪心+迪杰斯特拉)

最近做数学建模模拟赛,遇到一个公交调度的问题,原题给的两个附件,一个是每班公交的线路,另一个是所有教师的居住小区,然后题目要求给出一个既考虑服务质量(接最多的人)又考虑服务成本(走最短的路)的公交路线。
第一眼看这道题立马想到的是整理附件一的公交路线,整理出一个以公交车为行,以站点为列的矩阵,但附件有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];  
 }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值