Java实现旅行商问题

本文介绍了旅行商问题,即寻找一条经过n个城市且只访问一次的最短路径。通过哈密顿回路概念阐述问题,并提供了Java实现的解决方案。首先采用蛮力法解决小规模问题,接着利用减治思想,探讨了Johnson-Trotter算法和基于字典序的算法,旨在求解全排列并计算最短路径。
摘要由CSDN通过智能技术生成

1 问题描述
何为旅行商问题?按照非专业的说法,这个问题要求找出一条n个给定的城市间的最短路径,使我们在回到触发的城市之前,对每个城市都只访问一次。这样该问题就可以表述为求一个图的最短哈密顿回路的问题。(哈密顿回路:定义为一个对图的每个顶点都只穿越一次的回路)

很容易看出来,哈密顿回路也可以定义为n+1个相邻顶点v1,v2,v3,…,vn,v1的一个序列。其中,序列的第一个顶点和最后一个顶点是相同的,而其它n-1个顶点都是互不相同的。并且,在不失一般性的前提下,可以假设,所有的回路都开始和结束于相同的特定顶点。因此,可以通过生成n-1个中间城市的组合来得到所有的旅行线路,计算这些线路的长度,然后求取最短的线路。下图是该问题的一个小规模实例,并用该方法得到了它的解,具体如下:

2 解决方案
2.1 蛮力法

此处使用蛮力法解决旅行商问题,取的是4个城市规模,并已经定义好各个城市之间的距离(PS:该距离使用二维数组初始化定义,此处的距离是根据图1中所示距离定义)。此处主要是在体验使用蛮力法解决该问题的思想,如要丰富成普遍规模问题,还请大家自己稍微修改一下哒。对于代码中如碰到不能理解的地方,可以参考文章末尾给出的参考资料链接,以及相关代码注解~

具体代码如下:

package com.liuzhen.chapterThree;

public class TravelingSalesman {
    
    public int count = 0;     //定义全局变量,用于计算当前已行走方案次数,初始化为0
    public int MinDistance = 100;    //定义完成一个行走方案的最短距离,初始化为100(PS:100此处表示比实际要大很多的距离)
    public int[][] distance = {
  {0,2,5,7},{2,0,8,3},{5,8,0,1},{7,3,1,0}};   //使用二维数组的那个音图的路径相关距离长度
    /*
     * start为开始进行排序的位置
     * step为当前正在行走的位置
     * n为需要排序的总位置数
     * Max为n!值
     */
    public void Arrange(int[] A,int start,int step,int n,int Max){
        if(step == n){   // 当正在行走的位置等于城市总个数时
            ++count;           //每完成一次行走方案,count自增1
            printArray(A);     //输出行走路线方案及其总距离
        }
        if(count == Max)
            System.out.println("已完成全部行走方案!!!,最短路径距离为:"+MinDistance);  
        else{
            for(int i = start;i < n;i++){   
                /*第i个数分别与它后面的数字交换就能得到新的排列,从而能够得到n!次不同排序方案
                 * (PS:此处代码中递归的执行顺序有点抽象,具体解释详见本人另一篇博客:)  
                 *算法笔记_017:递归执行顺序的探讨(Java)
*/
                swapArray(A,start,i);
                Arrange(A,start+1,step+1,n,Max);
                swapArray(A,i,start);
            }
        }
    }
    
    //交换数组中两个位置上的数值
    public  void swapArray(int[] A,int p,int q){
        int temp = A[p];
        A[p] = A[q];
        A[q] = temp;
    }
    
    //输出数组A的序列,并输出当前行走序列所花距离,并得到已完成的行走方案中最短距离
    public void printArray(int[] A){
        for(int i = 0;i < A.length;i++)   //输出当前行走方案的序列
            
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值