POJ 1912 A highway and the seven dwarfs (凸包&O(logN)判断直线是否与凸包相交)
2014-02-22 21:33
477 查看
http://poj.org/problem?id=1912
思路:构造好凸包后,二分找凸包上第一个与正向直线夹角大于0的线段和第一个与反向直线夹角大于0的线段
然后判断两线段的起点是否在直线两侧即可。
完整代码:
思路:构造好凸包后,二分找凸包上第一个与正向直线夹角大于0的线段和第一个与反向直线夹角大于0的线段
然后判断两线段的起点是否在直线两侧即可。
完整代码:
/*2672ms,4624KB*/ #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const double pi = acos(-1.0); const double eps = 1e-10; ///这题不卡精度 const int mx = 100005; struct P { double x, y; P(double x = 0.0, double y = 0.0): x(x), y(y) {} bool read() { return ~scanf("%lf%lf", &x, &y); } ///由于比较的是原始输入数据,所以不用eps bool operator < (const P& p) const ///加cosnt和引用以便sort调用,其他函数不加 { return x < p.x || x == p.x && y < p.y; } P operator + (P p) { return P(x + p.x, y + p.y); } P operator - (P p) { return P(x - p.x, y - p.y); } P operator * (double d) { return P(x * d, y * d); } P operator / (double d) { return P(x / d, y / d); } double dot(P p) { return x * p.x + y * p.y; } double det(P p) { return x * p.y - y * p.x; } ///根据凸包构造之后的点的顺序,规定角度范围为(-pi/2, 3/(2pi)] double getA() { double A = atan2(y, x); if (A < -pi / 2.0 + eps) A += pi * 2; return A; } } p[mx], ans[mx], q1, q2; int n, len; double A[mx]; ///求凸包 void convex_hull() { sort(p, p + n); len = 0; int i; for (i = 0; i < n; ++i) { while (len >= 2 && (ans[len - 1] - ans[len - 2]).det(p[i] - ans[len - 1]) < eps) --len; ans[len++] = p[i]; } int tmp = len; for (i = n - 2; i >= 0; --i) { while (len > tmp && (ans[len - 1] - ans[len - 2]).det(p[i] - ans[len - 1]) < eps) --len; ans[len++] = p[i]; } --len; ans[len] = ans[0];///这句话直接写在凸包里 for (i = 0; i < len; ++i) A[i] = (ans[i + 1] - ans[i]).getA(); } inline bool dcmp(double a, double b) { return a + eps < b; } ///二分找第一个角度大于x的边 inline int Find(double angle) { return upper_bound(A, A + len, angle, dcmp) - A; } inline bool judge(P q1, P q2) { int i = Find((q2 - q1).getA()); int j = Find((q1 - q2).getA()); ///直线两侧各找一点,若两点在直线两侧,则直线必过凸包 if ((q2 - q1).det(ans[i] - q1) * (q2 - q1).det(ans[j] - q1) > -eps) return true; else return false; } int main() { scanf("%d", &n); for (int i = 0; i < n; ++i) p[i].read(); if (n > 1) convex_hull(); while (q1.read()) { q2.read(); puts(n <= 1 || judge(q1, q2) ? "GOOD" : "BAD"); } return 0; }
相关文章推荐
- POJ1912_A highway and the seven dwarfs_判断凸包与直线是否相交
- POJ 1912 A highway and the seven dwarfs(O(log N)求直线与凸包是否相交)
- POJ 3304 Segments (计算几何、判断直线与线段是否相交)
- poj 1410(判断直线是否相交)
- CodeForces - 593B Anton and Lines (数学方程&技巧) 判断直线是否相交
- POJ - 3304 :Segments__判断直线和线段是否 相交
- poj 3304 判断是否存在一条直线与所有线段相交
- UVALive 4639 && SPOJ SPOINTS && POJ 3805 && AOJ 1298 Separate Points 求两个凸包是否相交 难度:3
- poj 3304 判断是否有与所有线段相交的直线
- 判断直线与线段 是否相交 + 加入误差 故需要判断重点 poj 3304 Segments
- poj 3805 Separate Points 判断凸包是否相交,nlogn复杂度
- Segments - POJ 3304 (判断直线与线段是否相交)
- poj 3304 Segments 【判断是否存在一条直线与所有线段相交】
- POJ 3304 Segments(判断线段和直线是否相交)
- POJ 3304 Segments (判断直线和线段是否相交)
- (计算几何step8.1.2.1)POJ 2653 Pick-up sticks(判断一根木棒的上面时候还有其他木棒——判断两条直线是否相交)
- POJ 1228 Grandpa's Estate(判断是否稳定凸包)
- POJ 1264 SCUD Busters (凸包面积+判断点是否在凸包内)
- POJ 1039——计算几何初步(判断线段与直线相交)
- POJ 3304 判断线段 与 直线 相交