zoukankan      html  css  js  c++  java
  • 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;
    	}
    
    }
  • 相关阅读:
    C# WinForm下,隐藏主窗体,只在进程管理器中显示进程,在任务栏,状态栏都不显示窗体的方法
    C#全能数据库操作类及调用示例
    多个汇总列转换为行记录 mssql
    Oracle 10g创建数据库 用户等基本操作
    Jquery基本选择器 层次选择器 过滤选择器 表单选择器使用示例 带注释
    SQL与ORACLE的外键约束级联更新和删除
    C# 屏幕监控 自动截屏程序 主窗体隐藏,仅在进程中显示
    图文讲解VS2010程序打包操作 安装卸载
    查表法按日期生成流水号 mssql
    给DataTable添加主键 几何级提升Select筛选数据的速度
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13309594.html
Copyright © 2011-2022 走看看