Description
致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。我们
将H村抽象为一维的轮廓。如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描
述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可
以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长
希望建造的塔高度尽可能小。请你写一个程序,帮助dadzhi村长计算塔的最小高度。
Input
第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。
Output
仅包含一个实数,为塔的最小高度,精确到小数点后三位。
Sample Input
【输入样例一】
6
1 2 4 5 6 7
1 2 2 4 2 1
【输入样例二】
4
10 20 49 59
0 10 10 0
6
1 2 4 5 6 7
1 2 2 4 2 1
【输入样例二】
4
10 20 49 59
0 10 10 0
Sample Output
【输出样例一】
1.000
【输出样例二】
14.500
1.000
【输出样例二】
14.500
HINT
N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。
题解:半平面交。
在二维平面上连接前后两点,发现瞭望塔顶端必须在若干直线半平面交区域。
确定了塔顶的范围后,现在要求塔顶到轮廓线上的最近距离。
发现最近距离有两种可能:位于半平面交凸包上的顶点或位于轮廓线顶点处。
枚举求解。
这精度卡得也是可以。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int Maxn=550;
const int INF=0x3f3f3f3f;
int n,tot,L,R,cnt;
struct point{
double x,y;
point(double x=0,double y=0):x(x),y(y){}
friend inline point operator -(const point &a,const point &b){
return point(b.x-a.x,b.y-a.y);
}
friend inline double operator *(const point &a,const point &b){
return a.x*b.y-a.y*b.x;
}
}p[Maxn];
struct line{
point a,b;
double slope;
line(){}
line(point a,point b):a(a),b(b){}
friend inline bool operator <(const line &a,const line &b){
if(a.slope!=b.slope)return a.slope<b.slope;
return (a.a-b.b)*(b.a-b.b)>0;
}
friend inline point inter(const line &a,const line &b){
double k1=(a.b-b.b)*(a.a-b.b);
double k2=(a.a-b.a)*(a.b-b.a);
#define t (k1)/(k1+k2)
return point(b.b.x+(b.a.x-b.b.x)*t,b.b.y+(b.a.y-b.b.y)*t);
#undef t
}
}l[Maxn];
inline bool judge(line now,line a,line b){
point q=inter(now,a);
return (q-b.a)*(q-b.b)>0;
}
inline void hpi(){
sort(l+1,l+n);
for(int i=1;i<n;i++){
if(i==1||l[i].slope!=l[i-1].slope)l[++cnt]=l[i];
}
L=1,R=2;
for(int i=3;i<=cnt;i++){
while(L<R&&judge(l[i],l[R-1],l[R]))R--;
l[++R]=l[i];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf",&p[i].x);
for(int i=1;i<=n;i++){
scanf("%lf",&p[i].y);
if(i!=1){
l[i-1].a=p[i-1];l[i-1].b=p[i];
l[i-1].slope=atan2(l[i-1].b.y-l[i-1].a.y,l[i-1].b.x-l[i-1].a.x);
}
}
hpi();
int pos=L;
double ans=(double)INF*(double)INF;
for(int i=1;i<=n;i++){
while(pos!=R&&inter(l[pos],l[pos+1]).x<p[i].x)pos++;
point q=inter(line(p[i],point(p[i].x,-1.0)),l[pos]);
ans=min(ans,q.y-p[i].y);
}
pos=1;
for(int i=L;i<R;i++){
point q=inter(l[i],l[i+1]);
if(q.x<p[1].x)continue;
while(pos<n&&p[pos+1].x<q.x)pos++;
if(pos==n)break;
point t=inter(line(p[pos],p[pos+1]),line(q,point(q.x,-1.0)));
ans=min(ans,q.y-t.y);
}
printf("%.3f",ans);
}