【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
2016-02-05 16:18
459 查看
题目描述
致力于建设全国示范和谐小村庄的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,注意考虑实数误差带来的问题。题目分析
首先我们可以发现如果我们把每两个点之间连线,作为一个形如ax+by+c≤0ax+by+c\leq0或者大于等于等关系的式子我们求这样的式子的交集叫做求半平面交,那么我们可以发现在本题中,答案一定出现在半平面交的集合中,对于每两个点无论是村庄的轮廓点还是交集的边界点,我们可以发现如果做垂直于xx轴的直线我们可以划分成(令半平面交集的转折点数量为mm下面的村庄转折点数量为mm)那么我们可以将整个平面划分成n+m+1n+m+1块,在每一块中间都是由上下两个直线构成的,我们要求的答案就是每一块中两个直线距离最小的最小值,那么在每一块中因为上下都是支线,那么一定满足单调性,我们检查每一块的左右端点取较小值就行了。这里提供一个求半平面交集的方法(仅限本题目, 可以想一下为什么):/article/3720752.html
对于刚才的说明,我画了一张图,求得就是每两条绿色支线中黑色线段和红色线段距离的最小值
代码
[code]#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <stack> #include <cmath> #define mcp(a,b) fabs((a)-(b))<eps using 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; }
相关文章推荐
- 【POJ2773】Happy 2006 欧几里德
- 第二届蓝桥杯C/C++组第十题 Playfair密码变种加密
- clion1.2.2 破解-crack-注册码
- HTML5(九)canvas操作文字实例之转盘
- C#格式化数值结果表
- SharePoint2016 New Feature (Preview) - User Profile Service
- Linux 命令行参数解析整理
- OpenvSwitch实现Docker容器跨宿主机互联
- crc校验码生成程序(C#)
- Linux and the Unix Philosophy
- SVM: 使用kernels(核函数)的整个SVM算法过程
- HTML/CSS的学习过程一览
- Codevs_P1743 反转卡片(块状链表+SplayTree)
- 【最长上升子序列 - (n^2)】
- iOS 隐藏statusbar
- jQuery下的瀑布流效果(改)
- 关于上次ListView细节讲解
- 2016蓝桥杯历届试题——核桃的数量(最小公倍数)
- strcpy 溢出问题
- API调用