# 【bzoj1038】瞭望塔 半平面交

【输入样例一】
6
1 2 4 5 6 7
1 2 2 4 2 1
【输入样例二】
4
10 20 49 59
0 10 10 0

【输出样例一】
1.000
【输出样例二】
14.500

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 310
#define eps 1e-9
using namespace std;
typedef long double ld;
struct point
{
ld x , y;
point() {}
point(ld a , ld b) {x = a , y = b;}
point operator+(const point &a)const {return point(x + a.x , y + a.y);}
point operator-(const point &a)const {return point(x - a.x , y - a.y);}
point operator*(const ld &a)const {return point(x * a , y * a);}
bool operator<(const point &a)const {return x < a.x;}
}p[N] , c[N];
struct line
{
point p , v;
ld ang;
}a[N] , q[N];
inline ld cross(point a , point b) {return a.x * b.y - a.y * b.x;}
inline bool left(line a , point b) {return cross(a.v , b - a.p) > eps;}
inline point inter(line a , line b)
{
point u = a.p - b.p;
ld tmp = cross(b.v , u) / cross(a.v , b.v);
return a.p + a.v * tmp;
}
bool cmp(const line &a , const line &b)
{
return fabs(a.ang - b.ang) < eps ? left(a , b.p) :  a.ang < b.ang;
}
int main()
{
int n , i , l = 1 , r = 1 , t , tot = 1;
ld ans = 1e20;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ ) scanf("%Lf" , &p[i].x);
for(i = 1 ; i <= n ; i ++ ) scanf("%Lf" , &p[i].y);
for(i = 1 ; i < n ; i ++ ) a[i].p = p[i] , a[i].v = p[i] - p[i + 1] , a[i].ang = atan2(a[i].v.y , a[i].v.x);
a[n].p = point(0 , 1e20) , a[n].v = point(1 , 0) , a[n].ang = 0;
a[n + 1].p = point(p[1].x , p[1].y) , a[n + 1].v = point(-1e-10 , 1) , a[n + 1].ang = atan2(1 , 0);
a[n + 2].p = point(p[n].x , p[n].y) , a[n + 2].v = point(1e-10 , -1) , a[n + 2].ang = atan2(-1 , 0);
sort(a + 1 , a + n + 3 , cmp);
for(i = 2 ; i <= n + 2 ; i ++ )
if(fabs(a[i].ang - a[i - 1].ang) > eps)
a[++tot] = a[i];
q[1] = a[1];
for(i = 2 ; i <= tot ; i ++ )
{
while(l < r && left(a[i] , c[r - 1])) r -- ;
while(l < r && left(a[i] , c[l])) l ++ ;
q[++r] = a[i];
if(l < r) c[r - 1] = inter(q[r - 1] , q[r]);
}
while(l < r && left(q[l] , c[r - 1])) r -- ;
c[r] = inter(q[r] , q[l]);
sort(c + l , c + r + 1);
for(i = 1 , t = l ; i <= n ; i ++ )
{
while(t < r && c[t + 1] < p[i]) t ++ ;
ans = min(ans , (p[i].x - c[t].x) * (c[t + 1].y - c[t].y) / (c[t + 1].x - c[t].x) + c[t].y - p[i].y);
}
for(i = l , t = 1 ; i <= r ; i ++ )
{
if(c[i] < p[1] || p[n] < c[i]) continue;
while(t < n && p[t + 1] < c[i]) t ++ ;
ans = min(ans , c[i].y - (c[i].x - p[t].x) * (p[t + 1].y - p[t].y) / (p[t + 1].x - p[t].x) - p[t].y);
}
printf("%.3Lf\n" , ans);
return 0;
}


posted @ 2017-12-20 10:31  GXZlegend  阅读(369)  评论(0编辑  收藏  举报