Electric Fences 电网
农夫约翰已经决定建造电网.他已经把他的农田围成一些奇怪的形状,现在必须找出安放电源的最
佳位置.
对于段电网都必须从电源拉出一条电线.电线可以穿过其他电网或者跨过其他电线.电线能够以任
意角度铺设,从电源连接到一段电网的任意一点上(也就是,这段电网的端点上或者在其之间的任意
一点上).这里所说的“一段电网”指的是呈一条线段状的电网,并不是连在一起的几段电网.若几
段电网连在一起,那么也要分别给这些电网提供电力.
已知所有的 F(1 <= F <= 150)段电网的位置(电网总是和坐标轴平行,并且端点的坐标总是整数,0
<= X,Y <= 100).你的程序要计算连接电源和每段电网所需的电线的最小总长度,还有电源的最佳
坐标.
电源的最佳坐标可能在农夫约翰的农田中的任何一个位置,并不一是整数.
PROGRAM NAME: fence3
INPUT FORMAT
第一行包括 F ——电网的数量.
下面的 F 行每行包括两个 X,Y 对,表示这段电网的两个端点.
SAMPLE INPUT (file fence3.in)
3
0 0 0 1
2 0 2 1
0 3 2 3
OUTPUT FORMAT
只有一行,输出三个浮点数,相邻两个之间留一个空格.假定你的电脑的输出库会正确地对小数进行
四舍五入.
这三个数是:
电源最佳坐标的 X 值,
电源最佳坐标的 Y 值,和
需要的电线的总长度(要最小).
SAMPLE OUTPUT (file fence3.out)
1.6 3.7
分析:这题有很多随机化的算法,感觉不太靠谱,于是我用了一些正常一些的方法。由于电线总长是一个关于电源(x,y)的函数,我们可以三分x,再三分y,然后就能得到答案了。
#include
#define ll long long
#define ull unsigned long long
#define inf 1<<29
#define mp make_pair
#define pii pair
#define pb push_back
#define r1 rt<<1
#define r2 rt<<1|1
#define ld long double
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
return x*f;
}
const int N=155;
int n,a[N][4];
double ansd,ansx,ansy;
inline double sq(double x){return x*x;}
double calc(double x,double y){
double s=0;
for(int i=1;i<=n;++i){
double t=min(sqrt(sq(a[i][0]-x)+sq(a[i][1]-y)),sqrt(sq(a[i][2]-x)+sq(a[i][3]-y)));
if(a[i][1]==a[i][3]&&a[i][0]<=x&&x<=a[i][2]) t=min(t,fabs(a[i][1]-y));
if(a[i][0]==a[i][2]&&a[i][1]<=y&&y<=a[i][3]) t=min(t,fabs(a[i][0]-x));
s+=t;
}
return s;
}
double sfy(double x){
double l=0,r=100;
while(r-l>=0.01){
double mid=(l+r)/2;
double mid2=(r+mid)/2;
double t=calc(x,mid),t2=calc(x,mid2);
if(t=0.01){
double mid=(l+r)/2;
double mid2=(r+mid)/2;
double t=sfy(mid),t2=sfy(mid2);
if(t