您的位置:首页 > 编程语言 > Java开发

近似算法-欧几里得旅行商问题JAVA语言

2015-01-29 13:10 288 查看
1、问题描述

“旅行商问题”是指一名售货员要拜访多个地点时,如何找到从起始节拜访所有节点且仅拜访一次,最后回到起始节点的最短路径。最终形成的是一条闭合的回路,如图一所示。欧几里得旅行商问题是一种特殊的旅行商问题,它要求任意三个节点的距离满足三角形法则,即两边之和大于第三边,两边之差小于第三边。

                                                                                                 



                                                                                                                                                   图一 旅行商问题解结果

2、近似算法思想

所有的节点用相应的边连接起来构成一幅无向图,首先采用prim算法构造无向图的最小生成树,然后采用前序遍历的方法遍历无向图的最小生成树,遍历的结果就是售货员拜访所有节点的顺序。近似算法求的的拜访顺序所走过的路径不大于最短路径的2倍。prim算法的时间复杂度为O(n^2),n为节点的数量;前序遍历算法的时间复杂度为O(n),所以近似算法的时间复杂度为O(n^2),远小于动态规划法的时间复杂度O(2^n)。

3、JAVA代码

由于构造满足欧几里得旅行商问题的数据比较困难,本文假设所有节点都处于一个平面内,节点之间的距离为直线距离,因此输入参数为节点的坐标(x,y)。

3.1旅行商问题类

package approximation;

import java.util.Scanner;

public class approximation {

 private float edge[][],cost;

 private float city[][];

 private int start[],next[];

 private int TSP[],sit;

 public approximation(){

  Scanner sc=new Scanner(System.in);

  System.out.println("请输入城市的数量:");

  int num=sc.nextInt();

  city=new float[num][2];

  edge=new float[num][num];

  for(int i=0;i<num;i++){

   System.out.println("请输入第"+(i+1)+"个城市的位置:");

   city[i][0]=sc.nextFloat();

   city[i][1]=sc.nextFloat();

  }

  for(int i=0;i<num;i++){

   for(int j=0;j<num;j++){

    edge[i][j]=(float) Math.sqrt(Math.pow(city[i][0]-city[j][0], 2)+Math.pow(city[i][1]-city[j][1], 2));

   }

  }

 }

 public void approxTSP()

 {

  int n=city.length;

  float c[][]=edge;

  float[] lowcost = new float
;

  int[] clostest = new int
;

  boolean[] s = new boolean
;

  start = new int
;

  next = new int
;

  s[0] = true; //初始化,计算未遍历城市到已遍历集合的距离

  for (int i = 1; i <n; i++) {

   lowcost[i] = c[0][i];

   clostest[i] = 0;

   s[i] = false;

  }

  for (int i = 0; i < n-1; i++) {

   float min = Float.MAX_VALUE;

   int j = 0;

   for (int k = 1; k < n; k++) { //查找距离已遍历集合最近的城市

    if ((lowcost[k] < min) && (!s[k])) {

     min = lowcost[k];

     j = k;

    }

   }

   //System.out.println(clostest[j]+",  "+j); //输出并保存

   start[i] = clostest[j];

   next[i] = j;

   s[j] = true;

   for (int k = 1; k < n; k++) { //重新计算未遍历城市到已遍历集合的距离

    if (c[j][k] < lowcost[k] && (!s[k])) {

     lowcost[k] = c[j][k];

     clostest[k] = j;

    }

   }

  }

 }

 public void PreTra(){ //前序遍历最小生成树

  int n=city.length;

  TSP=new int
;

  sit=0;

  PreTraverse(0);

  System.out.println("旅行路径为:"); //输出并计算旅行代价

  cost=edge[TSP[n-1]][0];

  for(int i=0;i<n;i++){

   System.out.print(TSP[i]+" ");

   if(i<n-1){

    cost=cost+edge[TSP[i]][TSP[i+1]];

   }

  }

  System.out.print("\n旅行总代价为"+cost+"\n");

 }

 private void PreTraverse(int a) { //前序遍历最小生成树的递归代码

  int n=city.length;

  TSP[sit]=a;

  sit++;

  for(int i=0;i<n-1;i++){

   if(start[i]==a){

    PreTraverse(next[i]);

   }

  }

 }

}

3.2主函数使用旅行商问题类

package approximation;

public class TSP {

 /**

  * @param args

  */

 public static void main(String[] args) {

  // TODO Auto-generated method stub

  approximation approx=new approximation();

  approx.approxTSP(); //生成最小生成树

  approx.PreTra(); //前序遍历

 }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息