题意:给出一些电脑的二维坐标,连接两个电脑所用网线长为它们之间的直线距离再加上16 feet。要求把所有电脑连成一个串,怎样连,使得所用网线最短,并且按从一端到另一端的顺序输出连接的两个电脑间的距离。
思路:很容易想到的就是暴力枚举,将所有电脑做一个全排列,求得总长最小值的那个。这里用的递归枚举、即回溯法,进行了剪枝优化。
第一次交WA了,重读题目、看别人题解,都没找到原因。看到别人的freopen,才发现我交的里面freopen没注释掉~
Code:
#include<stdio.h> #include<math.h> void solve(int n,int *A,int cur,double dist); int comp[10][2]; int A[10];//排列 double C[10];//相邻两点间距离 int bestA[10]; double bestC[10]; double bestdist; int main() { //freopen("216.in","r",stdin); //freopen("216.out","w",stdout); int n; int num=1; while(scanf("%d",&n)==1 && n) { for(int i=0;i<n;++i) scanf("%d%d",&comp[i][0],&comp[i][1]); bestdist=1000000000; double dist=0; solve(n,A,0,dist); printf("**********************************************************\n"); printf("Network #%d\n",num++); for(int i=0;i<n-1;++i) printf("Cable requirement to connect (%d,%d) to (%d,%d) is %.2lf feet.\n" ,comp[bestA[i]][0],comp[bestA[i]][1],comp[bestA[i+1]][0],comp[bestA[i+1]][1],bestC[i]); printf("Number of feet of cable required is %.2lf.\n",bestdist); } return 0; } void solve(int n,int *A,int cur,double dist) { if(cur==n && dist<bestdist) { bestdist=dist; for(int i=0;i<n-1;++i) { bestC[i]=C[i]; bestA[i]=A[i]; } bestA[n-1]=A[n-1]; } else for(int i=0;i<n;++i) { int ok=1; for(int j=0;j<cur;++j) if(A[j]==i) { ok=0; break; } if(ok) { A[cur]=i; if(cur) { int dx=comp[A[cur]][0]-comp[A[cur-1]][0]; int dy=comp[A[cur]][1]-comp[A[cur-1]][1]; double jl=16+sqrt(dx*dx+dy*dy); C[cur-1]=jl; dist=dist+jl; if(jl<bestdist && dist<bestdist) solve(n,A,cur+1,dist); dist=dist-jl;//不要忘了这里的恢复。对枚举的每个i来说,dist应该是相同的。每一次i过来时,改变了dist的值,枚举下一个i时,应该把dist恢复。 } else solve(n,A,cur+1,dist);//不要忘了这个 } } }
原文地址:http://blog.csdn.net/buxizhizhou530/article/details/44018501