ZJOI 2008 瞭望塔 半平面交
来源:互联网 发布:英文翻译什么软件好 编辑:程序博客网 时间:2024/05/17 20:30
题意:
给出一个以n个点为轮廓的村庄,在村庄任意位置放一个瞭望塔,使瞭望塔能看到村庄的所有位置,求瞭望塔最低高度。
思路:
考虑轮廓的每一条边,要看到这条边就必须在这条边以上的一个半平面内,因此求半平面交即可,样例图:
不妨将半平面交与地面上的直线看成分段函数,分别为f(x)与g(x),则所求即为h(x) = f(x) - g(x)的最小值,由于f(x)与g(x)均为一次分段函数,故h(x)也是一次分段函数,其最值仅可能在每一段的端点处取到。
注意:
1)输入的坐标为整数,注意转为double
2)叉积代表有向面积,写的时候要想清楚方向
由于是第一次写半平面交,根据老人家的模板写的,其实由于本题的特殊性可以写得更简单(例如直线可用斜截式),但这样的写法更具一般性,代码:
#include <cstdio>#include <algorithm>#include <cmath>#define For(i,j,k) for(int i = j;i <= k;i++)#define dcmp(x) (x > eps ? 1 : (x < -eps ? -1 : 0))using namespace std;const int N = 310;const double eps = 1e-8;struct Point{ double x, y; Point(){} Point(double X, double Y):x(X), y(Y){} bool operator < (const Point& A) const{ return x < A.x; }};typedef Point Vector;Vector operator - (const Point &A, const Point &B){return Vector(A.x - B.x, A.y - B.y);}Point operator + (const Point &A, const Vector &V){return Point(A.x + V.x, A.y + V.y);}Vector operator * (const Vector &V, double k){return Vector(V.x * k, V.y * k);}double Cross(const Vector &A, const Vector &B){return A.x * B.y - A.y * B.x;}struct Line{ Point P; Vector v; double ang; Line(){} Line(const Point& A, const Point& B){ v = B - A; P = A; ang = atan2(v.y, v.x); } bool operator <(const Line& A) const{ return ang < A.ang; }};Point Intersection(Line& A, Line& B){ Vector v = A.P - B.P; double s = Cross(B.v, v) / Cross(A.v, B.v); return A.P + A.v * s;}bool Onleft(Line& L, Point& P){ return Cross(L.v, P - L.P) > 0;}int n, m;Line q[N], L[N];Point p[N], land[N];void HalfplaneIntersection(){ int l = 1, r = 1; sort(L + 1, L + n + 1); q[l] = L[1]; For(i,2,n){ while(l < r && !Onleft(L[i], p[r-1])) r--; while(l < r && !Onleft(L[i], p[l])) l++; q[++r] = L[i]; if(l < r && !dcmp(Cross(q[r].v, q[r-1].v))){ r--; if(Onleft(q[r], L[i].P)) q[r] = L[i]; } if(l < r) p[r-1] = Intersection(q[r-1], q[r]); } while(l < r && !Onleft(q[l], p[r-1])) r--; p[r] = Intersection(q[r], q[l]); For(i,l,r) p[i - l + 1] = p[i]; m = r - l + 1;}int x[N], y[N];int main(){ scanf("%d", &n); For(i,1,n) scanf("%d", &x[i]); For(i,1,n) scanf("%d", &y[i]), land[i] = Point(x[i], y[i]); For(i,1,n-1) L[i] = Line(land[i], land[i+1]); L[n] = Line(Point(1e12, 1e12), Point(-1e12, 1e12)); HalfplaneIntersection(); sort(p + 1, p + m + 1); double Ans = 1e12; For(i,1,n) For(j,1,m-1) if(dcmp(x[i] - p[j].x) >= 0 && dcmp(x[i] - p[j+1].x) <= 0){ Ans = min(Ans, p[j].y + (p[j+1].y - p[j].y) / (p[j+1].x - p[j].x) * (x[i] - p[j].x) - y[i]); break; } For(j,1,m) For(i,1,n-1) if(dcmp(p[j].x - x[i]) >= 0 && dcmp(p[j].x - x[i+1]) <= 0){ Ans = min(Ans, p[j].y - (1.0 * y[i] + 1.0 * (y[i+1] - y[i]) / (x[i+1] - x[i]) * (p[j].x - x[i]))); break; } printf("%.3lf\n", Ans); return 0;}
1 0
- ZJOI 2008 瞭望塔 半平面交
- BZOJ 1038 ZJOI 2008 瞭望塔 半平面交
- [BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- [省选前题目整理][BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
- bzoj1038 瞭望塔 半平面交
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- ZJOI2008 瞭望塔 半平面交
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- bzoj1038 瞭望塔【半平面交】
- ZJOI 2008 瞭望塔 三分法
- bzoj 1038 瞭望塔 半平面交 + 最小值 枚举
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- 【半平面交】[ZJOI2008][HYSBZ\BZOJ1038]瞭望塔
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- BZOJ 1038: [ZJOI2008]瞭望塔 半平面交
- 20. Valid Parentheses
- Android之RatingBar实现评论星级效果
- Android性能优化第(十)篇---布局优化
- 代数笔记-第二章-群
- 21. Merge Two Sorted Lists
- ZJOI 2008 瞭望塔 半平面交
- Android API Guide for Media and Camera(一)—— 媒体与相机(媒体播放器)
- Ubuntu下mysql常用操作
- atom添加背景颜色
- 100. Same Tree
- 指针和数组
- 106. Construct Binary Tree from Inorder and Postorder Traversal
- AWS坑
- Spring注解