题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=108&page=show_problem&problem=152
题目描述:
Getting in Line |
Computer networking requires that the computers in the network be linked.
This problem considers a ``linear" network in which the computers are chained together so that each is connected to exactly two others except for the two computers on the ends of the chain which are connected to only one other computer. A picture is shown below. Here the computers are the black dots and their locations in the network are identified by planar coordinates (relative to a coordinate system not shown in the picture).
Distances between linked computers in the network are shown in feet.
For various reasons it is desirable to minimize the length of cable used.
Your problem is to determine how the computers should be connected into such a chain to minimize the total amount of cable needed. In the installation being constructed, the cabling will run beneath the floor, so the amount of cable used to join 2 adjacent computers on the network will be equal to the distance between the computers plus 16 additional feet of cable to connect from the floor to the computers and provide some slack for ease of installation.
The picture below shows the optimal way of connecting the computers shown above, and the total length of cable required for this configuration is (4+16)+ (5+16) + (5.83+16) + (11.18+16) = 90.01 feet.
The input file will consist of a series of data sets. Each data set will begin with a line consisting of a single number indicating the number of computers in a network. Each network has at least 2 and at most 8 computers. A value of 0 for the number of computers indicates the end of input.
After the initial line in a data set specifying the number of computers in a network, each additional line in the data set will give the coordinates of a computer in the network. These coordinates will be integers in the range 0 to 150. No two computers are at identical locations and each computer will be listed once.
The output for each network should include a line which tells the number of the network (as determined by its position in the input data), and one line for each length of cable to be cut to connect each adjacent pair of computers in the network. The final line should be a sentence indicating the total amount of cable used.
In listing the lengths of cable to be cut, traverse the network from one end to the other. (It makes no difference at which end you start.) Use a format similar to the one shown in the sample output, with a line of asterisks separating output for different networks and with distances in feet printed to 2 decimal places.
6 5 19 55 28 38 101 28 62 111 84 43 116 5 11 27 84 99 142 81 88 30 95 38 3 132 73 49 86 72 111 0
********************************************************** Network #1 Cable requirement to connect (5,19) to (55,28) is 66.80 feet. Cable requirement to connect (55,28) to (28,62) is 59.42 feet. Cable requirement to connect (28,62) to (38,101) is 56.26 feet. Cable requirement to connect (38,101) to (43,116) is 31.81 feet. Cable requirement to connect (43,116) to (111,84) is 91.15 feet. Number of feet of cable required is 305.45. ********************************************************** Network #2 Cable requirement to connect (11,27) to (88,30) is 93.06 feet. Cable requirement to connect (88,30) to (95,38) is 26.63 feet. Cable requirement to connect (95,38) to (84,99) is 77.98 feet. Cable requirement to connect (84,99) to (142,81) is 76.73 feet. Number of feet of cable required is 274.40. ********************************************************** Network #3 Cable requirement to connect (132,73) to (72,111) is 87.02 feet. Cable requirement to connect (72,111) to (49,86) is 49.97 feet. Number of feet of cable required is 136.99.
题意:
给出一系列坐标位置的点,让你用一条线把他们都串起来,然后问怎样串,这条线的总长度最小。
题解:
一、利用stl中的next_permutation来模拟全排列的枚举,算出最小的情况。
二、利用暴力DFS把最短路径搜索出来。
开始做这题的时候有点过于注意那个2decimal了 ,结果看第一个样例数据的各个子段相加并不等于总长度,结果纠结了半天。。。。还因为double的精度问题wa了3次,现在搞明白就是那个总距离是各段还没有精确2位数的子段的double相加,而不是精确过后相加的。这里有可能会让某些人理解错题目的意思。
为什么不能用最小生成树,想了下,感觉是这样: 因为这个问题情境只能是串起来的点,就是说不是只要联通就行了,而是要一个接一个地串起来。讲具体点就是,这个问题情境的点的度数 只能是1 或者2 不可能有3 4 这种度数,而一般的最小生成树恰好是允许的,我想应该有特殊的最小生成树算法允许这样。。。。。
代码:
next_permutation:
/* topcoder codeforce acm uva 10474 - Where is the Marble? 2 decimal , the problem do not means 2 decimal in every pairs path length in the sum of the MinSum so the MinSum is added in every not 2 decimal double datas. */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h> #include<iostream> #include<string> #include<algorithm> #include<map> #include<vector> #define INF 99999999 using namespace std; typedef struct Points { int x; int y; Points() { x=0; y=0; } }Points,*PointsLink; Points List[10+5]; int ListLink[10+5];//the index address or index pointers to the List,that is to say the ListLink's value is List's index int N=0;// the number of the point double MinSum=INF; double Sum=0; int SaveLink[10+5]; double PathLenth[10+5];//the length is the SaveLink's divide 1 const char * OutputStr="Cable requirement to connect"; const char * Asterisks="**********************************************************"; int cases=0; /*get the distance between the two points*/ double Distance(Points A,Points B) { double dis=0; double X=abs(A.x-B.x); double Y=abs(A.y-B.y); dis=sqrt(X*X+Y*Y); dis=((int)(dis*100+0.5))/100.0+16;//2 decimal return(dis);//X=7 and Y=8 the double dis 2 decimal have a bug about it , you kan test it on yourself } /*calculate the sum path length*/ int CalcLenth(Points List[],int ListLink[]) { int i=0; for(i=0;i<=N-2;i++) { Sum+=Distance(List[ListLink[i]],List[ListLink[i+1]]); } Sum=((int)(Sum*100+0.5))/100.0; return(0); } /*get the distance between the two points*/ //double Distance1(Points A,Points B) //{ // double dis=0; // double X=abs(A.x-B.x); // double Y=abs(A.y-B.y); // dis=sqrt(X*X+Y*Y); // //dis=((int)(dis*100+0.5))/100.0+16;//2 decimal // dis+=16; // return(dis);//X=7 and Y=8 the double dis 2 decimal have a bug about it , you kan test it on yourself //} double Distance1(Points A,Points B) { return(sqrt(((double)A.x-(double)B.x)*((double)A.x-(double)B.x)+((double)A.y-(double)B.y)*((double)A.y-(double)B.y))+16); } /*calculate the sum path length*/ int CalcLenth1(Points List[],int ListLink[]) { int i=0; for(i=0;i<=N-2;i++) { Sum+=Distance1(List[ListLink[i]],List[ListLink[i+1]]); } //Sum=((int)(Sum*100+0.5))/100.0; return(0); } /*copy the linkpath*/ int LinkCpy(int SaveLink[],int ListLink[]) { int i=0; for(i=0;i<=N-1;i++) { SaveLink[i]=ListLink[i]; } return(0); } /*save the many two pairs path*/ int SavePathLenth(int SaveLink[]) { int i=0; for(i=0;i<=N-2;i++) { PathLenth[i]=Distance(List[SaveLink[i]],List[SaveLink[i+1]]); } return(0); } /*save the many two pairs path*/ int SavePathLenth1(int SaveLink[]) { int i=0; for(i=0;i<=N-2;i++) { PathLenth[i]=Distance1(List[SaveLink[i]],List[SaveLink[i+1]]); } return(0); } /*for test*/ int test() { return(0); } /*main process*/ int MainProc() { while(scanf("%d",&N)!=EOF&&N>0) { int i=0; cases++; MinSum=INF; for(i=0;i<=N-1;i++) { scanf("%d%d",&List[i].x,&List[i].y); ListLink[i]=i;//initialize the pointer array } do { if(ListLink[0]==2&&ListLink[1]==1&&ListLink[2]==4&&ListLink[3]==3&&ListLink[4]==0) { int ks=1; } Sum=0; //CalcLenth(List,ListLink);//calculate the sum path length CalcLenth1(List,ListLink);//calculate the sum path length if(Sum<MinSum) { MinSum=Sum; LinkCpy(SaveLink,ListLink); //SavePathLenth(SaveLink); SavePathLenth1(SaveLink); } }while(next_permutation(ListLink,ListLink+N)); printf("%s\n",Asterisks); printf("Network #%d\n",cases); for(i=0;i<=N-2;i++) { printf("%s",OutputStr); printf(" (%d,%d) to (%d,%d) is %.2lf feet.\n",List[SaveLink[i]].x,List[SaveLink[i]].y,List[SaveLink[i+1]].x,List[SaveLink[i+1]].y,PathLenth[i]); } printf("Number of feet of cable required is %.2lf.\n",MinSum); } return(0); } int main() { MainProc(); return(0); }
/* topcoder codeforce acm uva 10474 - Where is the Marble? not next_permutation we use brute DFS with per point as the start point and then DFS think about that why not use Minimum spanning tree????????????????? */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h> #include<iostream> #include<string> #include<algorithm> #include<map> #include<vector> #define INF 99999999 using namespace std; typedef struct Points { double x; double y; }Points,*PointsLink; Points List[10+5]; int Link[10+5]={0};//the n-1 link path int N=0; bool Vis[10+5]={false};//true means that we have used the point int MinLink[10+5]={0};//n-1 link path double MinSum=INF; double Sum=0; int cases=0; /*get distance between two points*/ double Dis(Points a,Points b) { return(sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))+16); } /*DFS the graph*/ int DFS(int cur,int cnt) { if(cnt==N) { Link[cnt-1]=cur; if(Sum<MinSum) { MinSum=Sum; memcpy(MinLink,Link,sizeof(Link)); } return(0); } else { if(Sum>=MinSum) { return(0); } int i=0; for(i=0;i<=N-1;i++) { if(!Vis[i]) { Vis[i]=true; Link[cnt-1]=cur;//recursive's structure is very important, good knowledge of it's level structure Sum+=Dis(List[cur],List[i]); DFS(i,cnt+1); Vis[i]=false; //Link Sum-=Dis(List[cur],List[i]); } } } return(0); } /*for test*/ int test() { return(0); } /*main process*/ int MainProc() { while(scanf("%d",&N)!=EOF&&N>0) { int i=0; cases++; for(i=0;i<=N-1;i++) { scanf("%lf%lf",&List[i].x,&List[i].y); } MinSum=INF; for(i=0;i<=N-1;i++)//let the List[i] as the start point { memset(Vis,false,sizeof(Vis)); Sum=0; Vis[i]=true; DFS(i,1); } printf("**********************************************************\n"); printf("Network #%d\n",cases); for(i=0;i<=N-2;i++) { printf("Cable requirement to connect (%.0lf,%.0lf) to (%.0lf,%.0lf) is %.2lf feet.\n",List[MinLink[i]].x,List[MinLink[i]].y,List[MinLink[i+1]].x,List[MinLink[i+1]].y,Dis(List[MinLink[i]],List[MinLink[i+1]])); } printf("Number of feet of cable required is %.2lf.\n",MinSum); } return(0); } int main() { MainProc(); return(0); }