# 「BZOJ1038」「洛谷P2600」「ZJOI2008」瞭望塔 半平面交+贪心

## 样例

### 样例输入

6
1 2 4 5 6 7
1 2 2 4 2 1


### 样例输出

1.000


## 题解

$$Code:$$

#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 100005
#define eps 1e-8
int n, m, h, t, cnt;
bool More(double a, double b){return a > b + eps;}
bool Less(double a, double b){return a < b - eps;}
bool Emore(double a, double b){return a > b - eps;}
bool Eless(double a, double b){return a < b + eps;}
bool Equal(double a, double b){return fabs(a - b) < eps;}
struct Point
{
double x, y;
Point(){}
Point(double a, double b){x = a, y = b;}
Point operator + (Point b){return Point(x + b.x, y + b.y);}
Point operator - (Point b){return Point(x - b.x, y - b.y);}
Point operator * (double c){return Point(x * c, y * c);}
Point operator / (double c){return Point(x / c, y / c);}
}A[N], B[N], p[N];
struct Line//直线、线段、射线s->t，向量为t-s
{
Point s, t;
Line(){};
Line(Point a, Point b){s = a, t = b;}
}S[N], q[N];
double Cross(Point a, Point b){return a.x * b.y - a.y * b.x;}
double Length(Point a){return sqrt(a.x * a.x + a.y * a.y);}
bool Onright(Line s, Point p){return More(Cross(p - s.s, s.t - s.s), 0);}
Point Intersect(Line a, Line b)
{
double s1 = Cross(a.t - a.s, b.s - a.s);
double s2 = Cross(b.t - a.t, a.t - a.s);
return b.s + (b.t - b.s) / (s1 + s2) * s1;
}
double Angle(Point p){return atan2(p.y, p.x);}
int cmp(Line s1, Line s2)//象限角度数越低的越靠前(-180,180]
{
Point a = s1.t - s1.s;
Point b = s2.t - s2.s;
if (!Equal(Angle(a), Angle(b)))return Angle(a) < Angle(b);
return Onright(s1, s2.s);
}
int cmp2(Point p1, Point p2){return p1.x < p2.x;}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lf", &A[i].x);
for (int i = 1; i <= n; i++)
scanf("%lf", &A[i].y);
for (int i = 1; i < n; i++)
S[++cnt] = Line(A[i], A[i + 1]);
S[++cnt] = Line(Point(A[1].x, 1e+12), Point(A[1].x, A[1].y));
S[++cnt] = Line(Point(A[n].x, 1e+12), Point(A[1].x, 1e+12));
S[++cnt] = Line(Point(A[n].x, A[n].y), Point(A[n].x, 1e+12));
sort(S + 1, S + cnt + 1, cmp);
int w = 1;
for (int i = 2; i <= cnt; i++)
if (!Equal(Angle(S[i].t - S[i].s), Angle(S[i - 1].t - S[i - 1].s)))
S[++w] = S[i];
cnt = w;
h = 1, t = 0;
q[++t] = S[1];
for (int i = 2; i <= cnt; i++)
{
while (h < t && Onright(S[i], p[t - 1]))t--;
while (h < t && Onright(S[i], p[h]))h++;
q[++t] = S[i];
if (h < t)
p[t - 1] = Intersect(q[t], q[t - 1]);
}
while (h < t && Onright(q[h], p[t - 1]))t--;
if (h < t)p[t] = Intersect(q[t], q[h]);
cnt = 0;
for (int i = h; i <= t; i++)
B[++cnt] = p[i];
sort(B + 1, B + cnt + 1, cmp2);
w = 1;
for (int i = 2; i <= cnt; i++)
if (Less(B[i].y, 1e+11))
B[++w] = B[i];
cnt = w;
double ans = 1e+10;
int w1 = 1, w2 = 2;
A[0].x = A[1].x - 1;
B[0].x = B[1].x - 1;
while (w1 <= cnt || w2 <= n)
{
if (w2 > n || (w1 <= cnt && B[w1].x < A[w2].x))
{
Point s = A[w2 - 1] + (A[w2] - A[w2 - 1]) / (A[w2].x - A[w2 - 1].x) * (B[w1].x - A[w2 - 1].x);
ans = min(ans, B[w1].y - s.y);
w1++;
}
else
{
Point s = B[w1 - 1] + (B[w1] - B[w1 - 1]) / (B[w1].x - B[w1 - 1].x) * (A[w2].x - B[w1 - 1].x);
ans = min(ans, s.y - A[w2].y);
w2++;
}
}
printf("%.3f\n", ans);
}

posted @ 2019-03-30 16:02  ModestStarlight  阅读(223)  评论(1编辑  收藏  举报