BZOJ 1038 ZJOI2008 瞭望塔 半平面交

75 篇文章 1 订阅
20 篇文章 0 订阅


#define FOR(i,j,k) for(i=j;i<=k;i++)
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int N = 20005;
struct Point {
    double x, y;
    Point(){}
    Point(double _x, double _y) : x(_x), y(_y) {}
    Point operator +(const Point &b) const { return Point(x + b.x, y + b.y); }
    Point operator -(const Point &b) const { return Point(x - b.x, y - b.y); }
    double operator *(const Point &b) const { return x * b.y - y * b.x; }
    Point operator *(double b) const { return Point(b * x, b * y); }
} p[N], poly[N];

struct Line {
    Point x, v;
    double ang;
    Line(){}
    Line(const Point &a, const Point &b) : x(a) {
        v = b - a;
        ang = atan2(v.y, v.x);
    }
    
    bool operator <(const Line &b) const {
        if (ang == b.ang) return v * (b.x - x) < 0;
        return ang < b.ang;
    }
    
    bool operator ==(const Line &b) const { return ang == b.ang; }
    
    Point intersection(const Line &b) {
        Point u = x - b.x;
        double t = (b.v * u) / (v * b.v);
        return x + v * t;
    }
} lines[N];

bool right(const Point &p, const Line &l) {
    return l.v * (p - l.x) < 0;
}

int half_plane_intersection(Line l[], int n, Point poly[]) {
    static Line q[N];
    sort(l + 1, l + n + 1);
    n = unique(l + 1, l + n + 1) - (l + 1);
    int f = 1, r = 0, m = 0;
    q[++r] = l[1]; q[++r] = l[2];
    for (int i = 3; i <= n; i++) {
        while (f < r && right(q[r].intersection(q[r - 1]), l[i])) r--;
        while (f < r && right(q[f].intersection(q[f + 1]), l[i])) f++;
        q[++r] = l[i];
    }
    while (f < r && right(q[r].intersection(q[r - 1]), q[f])) r--;
    while (f < r && right(q[f].intersection(q[f + 1]), q[r])) f++;
    q[r + 1] = q[f];
    for (int i = f; i <= r; i++)
        poly[++m] = q[i].intersection(q[i + 1]);
    return m;
}

int main() {
    int n, i, j, line_num = 0;
    double ans = 1e18;
    scanf("%d", &n);
    FOR(i,1,n) scanf("%lf", &p[i].x);
    FOR(i,1,n) scanf("%lf", &p[i].y);
    p[0] = Point(p[1].x, 100001);
    p[n + 1] = Point(p[n].x, 100001);
    FOR(i,1,n) {
        lines[++line_num] = Line(p[i - 1], p[i]);
        lines[++line_num] = Line(p[i], p[i + 1]);
    }
    int m = half_plane_intersection(lines, line_num, poly);
    FOR(j,1,m) FOR(i,1,n-1) {
        Point t(poly[j].x, -1);
        if (p[i].x <= t.x && t.x <= p[i + 1].x)
            ans = min(ans, poly[j].y -
                Line(p[i], p[i + 1]).intersection(Line(t, poly[j])).y);
    }
    FOR(j,1,n) FOR(i,1,m-1) {
        Point t(p[j].x, -1);
        if (poly[i].x <= t.x && t.x <= poly[i + 1].x)
            ans = min(ans, 
                Line(poly[i], poly[i + 1]).intersection(Line(t, p[j])).y
                - p[j].y);
    }
    printf("%.3lf", ans);
    return 0;
}

1038: [ZJOI2008]瞭望塔

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 1370   Solved: 596
[ Submit][ Status][ Discuss]

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

Sample Output

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

HINT

对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值