JAVA旅行商售货TSP

题目描述

有若干个城市,任何两个城市之间的距离都是确定的,现要求一旅行商从某城市出发必须经过每一个城市且只在一个城市逗留一次,最后回到出发的城市,问如何事先确定一条最短的线路以保证路径最短?

输入

输入两个整数n,m分别代表城市数量,边数量,2<=n<=8,n-1<=m<=2*n
接下来m行每行输入有3个整数x,y,z代表x和y城市之间有一条长为z的路,保证输入的图是连通的,旅行商总是从1城市出发。

输出

要求求出最短的路径,和该路径的长度,如果不存在这样的路径你只需要输出-1。

样例输入 Copy

4 6
1 2 30
1 3 6
1 4 4
2 3 5
2 4 10
3 4 20

样例输出 Copy

1 3 2 4 1
25

package book;

import java.util.Scanner;

public class TSP {
static int n,m;//n城市数量,m边数量
static int grh[][];//地图
static int curentlength,bestlength;//当前距离,最短距离
static int curent[],best[];//当前路线,最好的路线
static int Max=Integer.MAX_VALUE;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		m=sc.nextInt();
		grh=new int[n+1][n+1];
		curent=new int[n+1];
		best=new int[n+1];
		curentlength=0;
		bestlength=-1;
		for(int i=1;i<=n;i++) {
			curent[i]=i;
			for(int j=1;j<=n;j++) {
				grh[i][j]=Max;//初始化地图,每个点之间的距离都是无穷大
		   }
		}
		for(int i=1;i<=m;i++) {
			int start = sc.nextInt();
			int end = sc.nextInt();
			int length = sc.nextInt();
		    
		    	grh[start][end]=length;
		    	grh[end][start]=length;//把所有的边存储起来
		    
		}
		backtrace(2);
		if(bestlength!=-1) {
		for(int i=1;i<=n;i++) {
			System.out.print(best[i]+" ");
		}
		System.out.println("1");
		
		System.out.println(bestlength);
	}else {
		System.out.println("-1");
	}
		
	}

	
	private static void backtrace(int t) {
		if(t==n) {
			if(grh[curent[n-1]][curent[n]]!=Max&&grh[curent[n]][1]!=Max&&
					(curentlength+grh[curent[n-1]][curent[n]]+grh[curent[n]][1]<bestlength||bestlength==-1)) {
				//1.当到准备去第n个城市的时候,首先要判断当前售货员与第n个点有没有路线,没有路线就剪掉
				//2.要判断第n个点与起点1有没有路线,没有也要剪掉
				//3.判断走完这条路线,回到原点的总距离是不是小于已经知道的最短距离,如果大于也剪掉
				//如果都符合,就要做更新操作
				for(int i=1;i<=n;i++) {
					best[i]=curent[i];
				}
				bestlength=curentlength+grh[curent[n-1]][curent[n]]+grh[curent[n]][1];
			}
		}else {
			for(int i=t;i<=n;i++) {
				if(grh[curent[t-1]][curent[i]]<Max&&(curentlength+grh[curent[t-1]][curent[i]]<bestlength||bestlength==-1)) {
					//上面的剪枝条件是,t-1表示现在售货员所在的城市,i表示他现在要准备去的城市,两者之间必须要有边
					//bestlength=-1表示第一次走
					//符合条件我们就需要交换
					swap(t,i);
					curentlength=curentlength+grh[curent[t-1]][curent[t]];
					backtrace(t+1);
					curentlength=curentlength-grh[curent[t-1]][curent[t]];
				    swap(t,i);
				    
				}
			}
		}
		
	}
	private static void swap(int t, int i) {
		int temp=0;
		temp=curent[t];
		curent[t]=curent[i];
		curent[i]=temp;
	}

}
原文地址:https://www.cnblogs.com/hzcya1995/p/13309594.html