旅行售貨員問題的java實現(回溯法--排列樹)
具體問題描述以及C/C++實現參見網址
http://blog.csdn.net/liufeng_king/article/details/8890603
/**
* 圓排列問題--回溯法--排列樹
* @author Lican
*
*/
public class Circles {
public int n;//待排列圓的個數
public float min;//當前最優值
public float[] x;//當前圓排列圓心橫座標
public float[] r;//當前圓排列
public float circlePerm(int nn,float[] rr){
n=nn;
r=rr;
min=1000000;
x=new float[n+1];
backtrack(1);
return min;
}
public void backtrack(int t){
if(t>n)
compute();
else{
for(int j=t;j<=n;j++){
swap(r,t,j);
float centerx=center(t);
if(centerx+r[t]+r[1]<min){//下界約束
x[t]=centerx;
backtrack(t+1);
}
swap(r,t,j);
}
}
}
public void swap(float[] r,int i,int j){
float temp=r[i];
r[i]=r[j];
r[j]=temp;
}
public float center(int t){//計算當前所選擇圓的圓心橫座標
float temp=0;
for(int j=1;j<t;j++){
float valuex=(float) (x[j]+2.0*Math.sqrt(r[t]*r[j]));
if(valuex>temp)
temp=valuex;
}
return temp;
}
public void compute(){//計算當前圓排列的長度
float low=0;
float high=0;
for(int i=1;i<=n;i++){
if(x[i]-r[i]<low) low=x[i]-r[i];
if(x[i]+r[i]>high) high=x[i]+r[i];
}
if(high-low<min)
min=high-low;
}
public static void main(String[] args) {
int n=3;
float[] r={0,1,1,2};//r下標從1開始, 0無用,只是湊數
Circles c=new Circles();
float min=c.circlePerm(n, r);
System.out.println("最小圓排列長度爲"+min);
}
}
/*
輸出:
最小圓排列長度爲7.656854
*/