近似算法-欧几里得旅行商问题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(); //前序遍历
}
}
“旅行商问题”是指一名售货员要拜访多个地点时,如何找到从起始节拜访所有节点且仅拜访一次,最后回到起始节点的最短路径。最终形成的是一条闭合的回路,如图一所示。欧几里得旅行商问题是一种特殊的旅行商问题,它要求任意三个节点的距离满足三角形法则,即两边之和大于第三边,两边之差小于第三边。
图一 旅行商问题解结果
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(); //前序遍历
}
}
相关文章推荐
- 欧几里得旅行商问题 java与c++实现
- 欧几里得旅行商问题 java与c++实现
- Java多语言编码问题解析
- Java语言自身的安全性问题
- Java语言深入-构造函数的继承问题
- Java多语言编码问题解析
- 在基于 Java 语言的编程中我们经常遇到的一些问题
- Java多语言编码问题解析(1)
- Java语言的字符编码问题探讨
- 动态规划--双调欧几里得旅行商问题
- Java学习笔记之语言基础―― Java中浮点数除0问题
- JAVA基础:Java多语言编码问题解析
- 学习JAVA语言过程中遇到了一些问题
- Java多语言编码问题解析(2)
- 转贴:Java语言的十大问题及引申思考
- Java语言深入-构造函数的继承问题-Java基础-Java-编程开发
- Swing 写的客户端程序在java web start 运行,多语言过程中,JOptionPane.showMessageDialog() 按钮多语言问题
- JAVA基础:Java多语言编码问题解析
- 你必须知道的261个Java语言问题
- 你必须知道的JAVA语言问题(查查总结总结吧)