uva 216 Getting in Line

题目地址: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.

Input

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.

Output

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.

Sample Input

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

Sample Output

**********************************************************
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);
}




DFS:

/*

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);
}











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值