您的位置:首页 > 其它

【BOI2012】Mobile(mobile)

2017-10-07 22:07 423 查看

题目

在一个平面内有n个基站,每个基站有个坐标(xi,yi),现在要给每个基站设定一个相同的值,使基站覆盖x轴上(0,m)的所有点,求这个值最小要是多少。

PS:输入的点已按x为第一关键字y为第二关键字排序。

题解

①过滤无用点。②在此基础上利用单调栈维护对答案有用的点。③计算答案。

所谓无用点,就是当x相同时,abs(y)不是最小的点。(这很显然)

考虑正确答案的规律。

如果面前有一道题目,十分地棘手,那么很可能会有一个结论让你推,那请你根据题目给你的条件猜测一下这个结论是什么。这一点很重要。

假设有这么三个点A,B,C,设(x1,0)为AB的中垂线与X轴的交点,(x2,0)为BC的中垂线与X轴的交点。若x2<x1则点B为没用的点。详见图①。



x轴下方红色括号括起来的部分是A点比B点优的部分,绿色代表B比A优。

x轴下方绿色括号括起来的部分是B点比C点优的部分,绿色代表C比B优。

由于YC<YB,所以黄色部分优于其下方绿色部分。

很显然,上方绿色部分没有其下方的红色部分优。所以淘汰掉B点。

维护个单调栈就可以实现步骤②。

最后统计的答案大致为两点(最后筛出来的)中垂线与X轴的交点与其中一点的距离的最大值。

PS:注意边界。这是个很恶心的地方。

我们可以知道中垂线与X轴的交点的横坐标x单调递增。所以

①刚刚x进入[0,L]时,判断一下ans=max(ans,min(dis(0,0,x[d[i−1]],y[d[i−1]]),dis(0,0,x[d[i]],y[d[i]])))

②x∈[0,L],ans=max(ans,dis(temp,0,x[d[i]],y[d[i]]))

③x刚刚出[0,L]时,判断一下ans=max(ans,min(dis(L,0,x[d[i−1]],y[d[i−1]]),dis(L,0,x[d[i]],y[d[i]])))

然而还有一个更坑爹的地方,一定要考虑到。

④x一直∈[0,L]时,

ans=max(ans,dis(0,0,x[d[1]],y[d[1]]))

ans=max(ans,dis(L,0,x[d[tail]],y[d[tail]]))

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1000010
#define DB double
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int i,j,k,l,n,m,tot,last;
DB x
,y
,L;
DB K,B,X1,Y1,X,Y;
DB temp,temp1,ans,mx;
int head,tail,d
;
DB point(int i,int j){
DB K,X1,Y1,B;
K=(y[i]-y[j])/(x[i]-x[j]);
if(K==0){
return (x[j]+x[i])/2;
}
K=-1/K;
X1=(x[i]+x[j])/2;
Y1=(y[i]+y[j])/2;
B=Y1-X1*K;
return -B/K;
}
DB dis(DB X0,DB Y0,DB X1,DB Y1){return sqrt((X0-X1)*(X0-X1)+(Y0-Y1)*(Y0-Y1));}
int main(){
freopen("mobile.in","r",stdin);
freopen("mobile.out","w",stdout);
scanf("%d%lf",&n,&L);
x[0]=-2147483647;
fo(i,1,n){
scanf("%lf%lf",&X,&Y);
if(X>x[tot]){
tot++;
x[tot]=X;
y[tot]=Y;
} else
if(X==x[tot])if(abs(Y)<abs(y[tot]))y[tot]=Y;
}
last=0;
d[1]=0;
tail=0;
fo(i,1,tot){
while (tail>=2 && point(d[tail-1],d[tail])>=point(d[tail],i)) tail--;
d[++tail]=i;
}
ans=-2147483647;
temp=point(d[2],d[1]);
if(temp>0)ans=max(ans,dis(0,0,x[d[1]],y[d[1]]));
fo(i,2,tail){
temp=point(d[i],d[i-1]);
if(temp1<0 && temp>=0)
ans=max(ans,min(dis(0,0,x[d[i-1]],y[d[i-1]]),dis(0,0,x[d[i]],y[d[i]])));
if(temp>L && temp1<=L){
ans=max(ans,min(dis(L,0,x[d[i-1]],y[d[i-1]]),dis(L,0,x[d[i]],y[d[i]])));
}
if(temp>=0&&temp<=L)
ans=max(ans,dis(temp,0,x[d[i]],y[d[i]]));
temp1=temp;
}
if(temp<L)ans=max(ans,dis(L,0,x[d[tail]],y[d[tail]]));
printf("%.6lf",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: