给出n个结点的横纵坐标,将它们连成一条线,怎么样使他们的的距离最小。
用回朔法,以任意一个为起点,先连到最后一个,然后回朔。
若比当前最小值小,则用数组记录路线。
#include<cstdio>
#include<cstring>
#include<cmath>
const int MAXN=10;
double dis(int x1,int y1,int x2,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
typedef struct{
int x,y,father;
double dis;
}solve;
solve a[MAXN];
int minf[MAXN],minfather,n; //最后一个结点,数组记录最佳结点的路线
double ans,temp,mindis[MAXN];
bool vis[MAXN];
void input(int n,int cur){ //递归输出有路线
if(cur==0) return ;
input(minf[n],cur-1);
printf("Cable requirement to connect (%d,%d) to (%d,%d) is %.2f feet.\n",a[minf[n]].x,a[minf[n]].y,a[n].x,a[n].y,mindis[n]);
}
void dfs(int cur,int father){
if(temp>ans) return ;
if(cur==n){
if(temp<=ans) {
ans=temp;
minfather=father;
for(int i=0;i<n;i++) { //记得更新路线
mindis[i]=a[i].dis;
minf[i]=a[i].father;
}
}
return ;
}
else for(int i=0;i<n;i++) if(!vis[i]){
if(father!=-1) a[i].dis = dis(a[i].x,a[i].y,a[father].x,a[father].y)+16; //电缆的长度比距离多16
else a[i].dis=0;
a[i].father=father;
vis[i]=true;
temp+=a[i].dis;
dfs(cur+1,i);
vis[i]=false;
temp-=a[i].dis; //注意回朔
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int cnt=0;
while(~scanf("%d",&n)){
ans=1000000;
if(n==0) break;
memset(vis,false,sizeof(vis));
for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
dfs(0,-1);
printf("**********************************************************\n");
cnt++; printf("Network #%d\n",cnt);
input(minfather,n-1);
printf("Number of feet of cable required is %.2f.\n",ans);
}
return 0;
}