农夫约翰已经决定建造电网。他已经把他的农田围成一些奇怪的形状,现在必须找出安放电源的最佳位置。
对于每段电网都必须从电源拉出一条电线。电线可以穿过其他电网或者跨过其他电线。电线能够以任意角度铺设,从电源连接到一段电网的任意一点上(也就是,这段电网的端点上或者在其之间的任意一点上)。这里所说的“一段电网”指的是呈一条线段状的电网,并不是连在一起的几段电网。若几段电网连在一起,那么也要分别给这些电网提供电力。
已知所有的 F(1 <= F <= 150)段电网的位置(电网总是和坐标轴平行,并且端点的坐标总是整数,0 <= X,Y <= 100)。你的程序要计算连接电源和每段电网所需的电线的最小总长度,还有电源的最佳坐标。
电源的最佳坐标可能在农夫约翰的农田中的任何一个位置,并不一定是整数。
格式
PROGRAM NAME: fence3
INPUT FORMAT
第一行包括 F ——电网的数量。下面的 F 行每行包括两个 X,Y 对,表示这段电网的两个端点。
OUTPUT FORMAT
只有一行,输出三个浮点数,相邻两个之间留一个空格。假定你的电脑的输出库会正确地对小数进行四舍五入。
这三个数是:
电源最佳坐标的 X 值,电源最佳坐标的 Y 值,和需要的电线的总长度(要最小)。
SAMPLE INPUT (file fence3.in)
3
0 0 0 1
2 0 2 1
0 3 2 3
SAMPLE OUTPUT (file fence3.out)
1.0 1.6 3.7
【参考程序】:
/*
ID: XIONGNA1
PROG: fence3
LANG: C++
*/
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
struct node
{
int x,y;
} s[151][2];
double ans,tx,ty;
int n;
void Swap(node a,node b)
{
node t=a;a=b;b=t;
}
double sqr(double x)
{
return x*x;
}
double MIN(double x,double y)
{
if (x<y) return x;
else return y;
}
double dis(double x,double y)
{
double sum=0,s1,s2;
for (int i=1;i<=n;i++)
if (s[i][0].x<x && x<s[i][1].x)
sum+=abs(s[i][0].y-y);
else if (s[i][0].y<y && y<s[i][1].y)
sum+=abs(s[i][0].x-x);
else
{
s1=sqrt(sqr(s[i][0].x-x)+sqr(s[i][0].y-y));
s2=sqrt(sqr(s[i][1].x-x)+sqr(s[i][1].y-y));
sum+=MIN(s1,s2);
}
return sum;
}
int main()
{
freopen("fence3.in","r",stdin);
freopen("fence3.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&s[i][0].x,&s[i][0].y,&s[i][1].x,&s[i][1].y);
if (s[i][0].x>s[i][1].x || s[i][0].y>s[i][1].y)
Swap(s[i][0],s[i][1]);
}
double x,y,d,temp;
tx=ty=0; d=10; ans=9999999.9;
while (d>=0.001)
{
for (int i=0;i<=10;i++)
for (int j=0;j<=10;j++)
{
temp=dis(tx+d*j,ty+d*i);
if (temp<ans)
{
ans=temp;
x=tx+d*j; y=ty+d*i;
}
}
tx=x-d; ty=y-d;
d/=5;
}
printf("%.1lf %.1lf %.1lf\n",tx,ty,ans);
return 0;
}