【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
来源:互联网 发布:super java 编辑:程序博客网 时间:2024/05/22 02:30
题目描述
致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。我们将H村抽象为一维的轮廓。如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长希望建造的塔高度尽可能小。请你写一个程序,帮助dadzhi村长计算塔的最小高度。
第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。
仅包含一个实数,为塔的最小高度,精确到小数点后三位。
样例输入
【输入样例一】
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
HINT
对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。
题目分析
首先我们可以发现如果我们把每两个点之间连线,作为一个形如
这里提供一个求半平面交集的方法(仅限本题目, 可以想一下为什么):http://blog.csdn.net/jeremygjy/article/details/50623877
对于刚才的说明,我画了一张图,求得就是每两条绿色支线中黑色线段和红色线段距离的最小值
代码
#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <vector>#include <stack>#include <cmath>#define mcp(a,b) fabs((a)-(b))<epsusing namespace std;const int MAXN = 300;const double eps = 1e-8;const int INF = 1000000000;struct Point{ double x, y; Point(){x=y=0;} bool operator<(const Point& pt) const{ return x < pt.x; } bool operator>(Point pt) const{ return x > pt.x; }}List[MAXN+10], List2[MAXN+10];struct Line{ double a, b; Point GetD(const Line& c){ Point ret; ret.x = (1.0 * (c.b - b)) / (a - c.a); ret.y = a * ret.x + b; return ret; } void Make(Point _a, Point _b){ a = (_a.y - _b.y) / (_a.x - _b.x); b = _a.y - a * _a.x; } bool operator == (const Line& c) { return c.a + eps >= a && c.a - eps <= a; }}T[MAXN+10];stack<Line> ans;stack<Point> jd;bool cmp(Line a, Line b){ if(mcp(a.a, b.a)) return a.b < b.b; return a.a < b.a;}bool cmp3(Point a, Point b){ return a.x < b.x;}int pcmp(Point p, Line l){ double y = l.a * p.x + l.b; if(y >= p.y-eps) return -1; return 1;}void solve(int n){ int tn = 0; sort(T+1, T+1+n, cmp); for(int i=1;i<=n;i++){ while(mcp(T[i].a,T[i+1].a)) i++; T[++tn] = T[i]; } ans.push(T[1]); for(int i=2;i<=tn;i++){ while(!jd.empty()){ Point tp = jd.top(); if(pcmp(tp, T[i]) <= 0){ jd.pop(); ans.pop(); }else break; } jd.push(T[i].GetD(ans.top())); ans.push(T[i]); }}int main(){ Line tmp; int n; scanf("%d", &n); for(int i=1;i<=n;i++) scanf("%lf", &List[i].x); for(int i=1;i<=n;i++) scanf("%lf", &List[i].y); for(int i=2;i<=n;i++) T[i-1].Make(List[i-1], List[i]); solve(n-1); int cnt = 0; while(!jd.empty()){ List2[++cnt] = jd.top(); jd.pop(); } sort(List2+1, List2+1+cnt, cmp3); double answer = 1e20; for(int i=1;i<n;i++){ tmp.Make(List[i], List[i+1]); int pos = lower_bound(List2+1, List2+1+cnt, List[i]) - List2; for(int j=pos;List2[j].x <= List[i+1].x+eps && j <= cnt;j++) answer = min(answer, max(0.0 , List2[j].y - List2[j].x*tmp.a - tmp.b)); } int ct2 = ans.size(); int ctmp = ct2; while(!ans.empty()){ T[--ct2] = ans.top(); ans.pop(); } ct2 = ctmp; int tp = lower_bound(List+1, List+1+n, List2[1]) - List; if(List[tp].x >= List2[1].x-eps) tp--; while(tp){ answer = min(answer, max(0.0, T[0].a*List[tp].x+T[0].b-List[tp].y)); tp--; } tp = lower_bound(List+1, List+1+n, List2[cnt]) - List; while(tp <= n){ answer = min(answer, max(0.0, T[cnt].a*List[tp].x+T[cnt].b-List[tp].y)); tp++; } for(int i=1;i<cnt;i++){ tp = lower_bound(List+1, List+1+n, List2[i]) - List; for(int j=tp;List[j].x <= List2[i+1].x && j <= n;j++) answer = min(answer, max(0.0, T[i].a*List[j].x+T[i].b-List[j].y)); } printf("%.3lf\n", answer); return 0;}
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- 【BZOJ1038】[ZJOI2008]瞭望塔 计算几何 半平面交/模拟退火+二分
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- 【半平面交】[ZJOI2008][HYSBZ\BZOJ1038]瞭望塔
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- bzoj1038:[ZJOI2008]瞭望塔(半平面交)
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- [BZOJ1038][洛谷P2600]-[ZJOI2008]瞭望塔-半平面交
- bzoj1038 [ZJOI2008]瞭望塔(半平面交)
- bzoj1038 瞭望塔 半平面交
- bzoj1038 瞭望塔【半平面交】
- ZJOI2008 瞭望塔 半平面交
- 【BZOJ1038】【codevs1412】瞭望塔,半平面交/三分法
- bzoj1038: [ZJOI2008]瞭望塔
- 【ZJOI2008】【BZOJ1038】瞭望塔
- bzoj1038[ZJOI2008]瞭望塔
- C#格式化数值结果表
- SharePoint2016 New Feature (Preview) - User Profile Service
- QT【绘图】 QPaintDevice 总结:QPixmap、QImage、QBitmap和QPicture
- 数据结构的基本概念
- HttpServlet详解
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- Kali Linux, Rolling Edition Released – 2016.1安装vm tool
- Spark Streaming 实现思路与模块概述
- 前台线程(Foreground Threads)和后台线程(Background Threads) .
- Eclipse代码提示
- [6] CMake总结 - 3 IF WHILE FOREACH MACRO FUNCTION
- python
- ASP.NET 中 Winform 的一些使用
- Plugin is too old, please update to a more recent version, or set ANDROID_DAILY_OVERRIDE envrinment