zoukankan      html  css  js  c++  java
  • Java实现旅行商最短距离

    旅行商问题

    旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题。经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,它是一个NP完全问题。由于其在交通运输、电路板线路设计以及物流配送等领域内有着广泛的应用,国内外学者对其进行了大量的研究。早期的研究者使用精确算法求解该问题,常用的方法包括:分枝定界法、线性规划法、动态规划法等。但是,随着问题规模的增大,精确算法将变得无能为力,因此,在后来的研究中,国内外学者重点使用近似算法或启发式算法,主要有遗传算法模拟退火法蚁群算法禁忌搜索算法、贪婪算法神经网络

    DisMinGraph.java

      1 package com.itheima.controller;
      2 
      3 import java.util.ArrayList;
      4 import java.util.Arrays;
      5 import java.util.Scanner;
      6 public class DisMinGraph {
      7     static final int  MaxValue=65535;               //最大值(可设为一个最大整数)
      8     static Scanner input=new Scanner(System.in);
      9 
     10     public static void main(String[] args) {
     11         GraphMatrix GM=new GraphMatrix();       //定义保存邻接表结构的图
     12         System.out.printf("求解最短路径问题!
    ");
     13         System.out.println("请输入图顶点数!");
     14         int VertexNum=input.nextInt();
     15         System.out.println("请输入图顶点数");
     16         int EdgeNum=input.nextInt();            //输入图边数
     17         char[] points=new char[VertexNum];      //读取顶点信息
     18         char[][] roads=new char[EdgeNum][2];    //读取边信息,起点和终点
     19         int[] weight=new int[EdgeNum];          //读取边权重
     20         System.out.println("请输入图论中的顶点符号:例如:C1,C2,C3,C4,C5");
     21         for(int i=0;i<points.length;i++){
     22             points[i]=(input.next().toCharArray())[0];
     23         }
     24         System.out.println("请输入顶点 顶点 权值,例如:C1 C2 7");
     25         for(int i=0;i<roads.length;i++){
     26             roads[i][0]=(input.next().toCharArray())[0];
     27             roads[i][1]=(input.next().toCharArray())[0];
     28             weight[i]=input.nextInt();
     29         }
     30         CreateGraph(GM,points,roads,weight);    //生成邻接表结构的图
     31 //      OutGraph(GM);                           //输出邻接矩阵
     32         System.out.println("请输入出发点!例如:C1");
     33         int vend=GM.indexOf((input.next().toCharArray())[0]);   //获取出发点位置
     34         if(vend==-1){
     35             System.out.println("顶点不存在,请重新输入!");
     36             return;
     37         }
     38         int[][] disMin=DistMin(GM,vend);        //执行最小路径算法
     39         System.out.println("各顶点到达顶点“"+GM.Vertex[vend]+"”的最短路径分别为(起始点 - 结束点):");
     40         int max=0;
     41         String cc="";
     42         for(int i=0;i<GM.VertexNum;i++)         //各个顶点到出发点的路径
     43         {
     44             char[][] path=getPath(GM,disMin,vend,i);
     45             if(max<(int)path[1][0]){
     46                 max=(int)path[1][0];
     47                 cc= Arrays.toString(path[0]);
     48             }
     49             System.out.println("-->"+Arrays.toString(path[0])+"-------------->路径长度:"+(int)path[1][0]);
     50         }
     51         System.out.println("行最长路径的最短距离-->"+Arrays.toString(new String[]{cc})+"-------------->路径长度:"+max);
     52 
     53     }
     54 
     55     private static void CreateGraph(GraphMatrix GM,char[] points,char[][] roads,int[] weights){     //创建邻接矩阵图
     56         GM.setVertex(points);
     57         GM.setEdgeWeight(roads, weights);
     58     }
     59     /**
     60      * 输出图的邻接矩阵
     61      * @param GM
     62      */
     63     public static void OutGraph(GraphMatrix GM)
     64     {
     65         int i,j;
     66         System.out.print("
    ");
     67         for(i=0;i<GM.VertexNum;i++)
     68         {
     69             for(j=0;j<GM.VertexNum;j++)
     70             {
     71                 if(GM.EdgeWeight[i][j]==MaxValue) //若权值为最大值
     72                 {
     73                     System.out.print("	Z");                //以Z表示无穷大
     74                 }
     75                 else
     76                 {
     77                     System.out.print("	"+GM.EdgeWeight[i][j]); //输出边的权值
     78                 }
     79             }
     80             System.out.print("
    ");
     81         }
     82     }
     83 
     84     private static int[][] DistMin(GraphMatrix GM,int vend)         //最短路径算法
     85     {
     86         //可到达指定顶点(出发点)的顶点集合,下标表示顶点位置,值表示是否可以到达,0表示不能,1表示能
     87         int[] tmpvertex=new int[GM.VertexNum];
     88         //从所有顶点到达指定顶点(出发点)的路径索引数组;下标为对应顶点,值为对应顶点可到达的下一个顶点
     89         int[] path=new int[GM.VertexNum];
     90         int[] weight=new int[GM.VertexNum];         //某终止点到各顶点的最短路径长度
     91         for(int i=0;i<GM.VertexNum;i++)             //初始weight数组
     92         {
     93             tmpvertex[i]=0;                     //初始化顶点集合为空
     94             weight[i]=GM.EdgeWeight[vend][i];   //保存最小权值
     95             if(weight[i]<MaxValue && weight[i]>0) //有效权值
     96             {
     97                 path[i]=vend;               //保存边
     98             }
     99         }
    100         tmpvertex[vend]=1;                  //选入顶点vend
    101         weight[vend]=0;
    102         for(int i=0;i<GM.VertexNum;i++)
    103         {
    104             int min=MaxValue;
    105             int k=vend;
    106             for(int j=0;j<GM.VertexNum;j++)         //查找未用顶点的最小权值
    107             {
    108                 if(tmpvertex[j]==0 && weight[j]<min)
    109                 {
    110                     min=weight[j];
    111                     k=j;
    112                 }
    113             }
    114             tmpvertex[k]=1;                     //将顶点k选为可到达指定定点(出发点)
    115             for(int j=0;j<GM.VertexNum;j++)         //以顶点k为中间点,重新计算权值 ,判断是否有以顶点k为中继到达指定定点(出发点)权值更小的点
    116             {
    117                 if(tmpvertex[j]==0 && weight[k]+GM.EdgeWeight[k][j]<weight[j])
    118                 {
    119                     weight[j]=weight[k]+GM.EdgeWeight[k][j];
    120                     path[j]=k;
    121                 }
    122             }
    123         }
    124         return new int[][]{tmpvertex,path};
    125     }
    126 
    127     public static char[][] getPath(GraphMatrix GM,int[][] disMin,int vend,int end){
    128         ArrayList<Character> path=new ArrayList<Character>();
    129         int l=0;
    130         if(disMin[0][end]==1)
    131         {
    132             int k=end;
    133             while(k!=vend)
    134             {
    135                 path.add(GM.Vertex[k]);
    136                 l+=GM.EdgeWeight[k][disMin[1][k]];
    137                 k=disMin[1][k];
    138             }
    139             path.add(GM.Vertex[k]);
    140         }
    141         char[] p=new char[path.size()];
    142         for(int i=0;i<p.length;i++){
    143             p[i]=path.get(i);
    144         }
    145         return new char[][]{p,{(char)l}};
    146     }
    147 
    148 }

    Graph.java

     1 package com.itheima.controller;
     2 /**
     3  * 新建Graph类,用于存储数据
     4  * @author Misui_user
     5  *
     6  */
     7 class GraphMatrix
     8 {
     9     public static final int  MaxValue=65535;        //最大值(可设为一个最大整数)
    10     char[] Vertex;                                  //保存顶点信息(序号或字母)
    11     int GType=0;                                    //图的类型(0:无向图,1:有向图)
    12     int VertexNum;                                  //顶点的数量
    13     int EdgeNum;                                    //边的数量
    14     int[][] EdgeWeight;                             //保存边的权
    15     /**
    16      * 设置顶点
    17      * @param points
    18      */
    19     public void setVertex(char[] points){
    20         this.Vertex=new char[points.length];
    21         this.VertexNum=points.length;
    22         for(int i=0;i<this.VertexNum;i++)           //输入顶点
    23         {
    24             this.Vertex[i]=points[i];               //保存到各顶点数组元素中
    25         }
    26     }
    27     /**
    28      * 设置边及其权重
    29      * @param roads
    30      * @param weights
    31      */
    32     public void setEdgeWeight(char[][] roads,int[] weights){
    33         this.EdgeWeight=new int[roads.length][roads.length];
    34         ClearGraph();
    35         this.EdgeNum=roads.length;
    36         for(int k=0;k<this.EdgeNum;k++)         //输入边的信息
    37         {
    38             int i=indexOf(roads[k][0]);     //在已有顶点中查找始点位置
    39             int j=indexOf(roads[k][1]);     //在已有顶点中查找结终点 位置
    40             this.EdgeWeight[i][j]=weights[k];       //对应位置保存权值,表示有一条边
    41             if(this.GType==0)               //若是无向图
    42             {
    43                 this.EdgeWeight[j][i]=weights[k];   //在对角位置保存权值
    44             }
    45         }
    46     }
    47     /**
    48      * 清空邻接矩阵
    49      * @param GM
    50      */
    51     private void ClearGraph()
    52     {
    53         for(int i=0;i<this.VertexNum;i++)       //清空矩阵
    54         {
    55             for(int j=0;j<this.VertexNum;j++)
    56             {
    57                 this.EdgeWeight[i][j]=MaxValue; //设置矩阵中各元素的值为MaxValue
    58             }
    59         }
    60     }
    61     public int indexOf(char c){
    62         for(int i=0;i<VertexNum;i++){
    63             if(c==Vertex[i]){
    64                 return i;
    65             }
    66         }
    67         return -1;
    68     }
    69 }

    运行结果说明:

  • 相关阅读:
    在Windows下Mysql如何重置root用户密码
    textrendering 详解
    修复IE6 PNG不透明问题的最佳解决方案
    机电传动控制第一周学习笔记
    WEB架构师成长之路之二大牛的法宝
    WEB架构师成长之路之一走正确的路
    WEB架构师成长之路之三架构师都要懂哪些知识
    hdu 1081 To The Max(最大子段和的升级版,二维)
    hdu 1080 (DP LCS最长公共子序列)
    添加\删除注册表项
  • 原文地址:https://www.cnblogs.com/chenqiwei/p/RunWsh_lxszdjl.html
Copyright © 2011-2022 走看看