poj 3335 Rotating Scoreboard (Half Plane Intersection)
给出一个多边形,要求判断它的内核是否存在。
还是半平面交的题,在这道题中,公告板允许其所在位置与直线共线也算是可见,于是我们就可以将每一条直线微小的移动,然后判断是够能够交出多边形,这样做是因为对于半平面交是不能直接判断是够交集是一个点的情况的。
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 8 using namespace std; 9 10 struct Point { 11 double x, y; 12 Point() {} 13 Point(double x, double y) : x(x), y(y) {} 14 } ; 15 template<class T> T sqr(T x) { return x * x;} 16 typedef Point Vec; 17 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);} 18 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);} 19 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);} 20 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);} 21 22 const double EPS = 1e-8; 23 const double PI = acos(-1.0); 24 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 25 26 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;} 27 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;} 28 inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);} 29 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);} 30 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));} 31 inline double toRad(double deg) { return deg / 180.0 * PI;} 32 inline double angle(Vec v) { return atan2(v.y, v.x);} 33 inline Vec vecUnit(Vec x) { return x / vecLen(x);} 34 inline Vec normal(Vec x) { return Vec(-x.y, x.x) / vecLen(x);} 35 36 const int N = 111; 37 struct DLine { 38 Point p; 39 Vec v; 40 double ang; 41 DLine() {} 42 DLine(Point p, Vec v) : p(p), v(v) { ang = atan2(v.y, v.x);} 43 bool operator < (DLine L) const { return ang < L.ang;} 44 DLine move(double x) { 45 Vec nor = normal(v); 46 nor = nor * x; 47 return DLine(p + nor, v); 48 } 49 } dl[N]; 50 Point pt[N]; 51 52 inline bool onLeft(DLine L, Point p) { return crossDet(L.v, p - L.p) > 0;} 53 Point dLineIntersect(DLine a, DLine b) { 54 Vec u = a.p - b.p; 55 double t = crossDet(b.v, u) / crossDet(a.v, b.v); 56 return a.p + a.v * t; 57 } 58 59 struct Poly { 60 vector<Point> pt; 61 Poly() { pt.clear();} 62 ~Poly() {} 63 Poly(vector<Point> &pt) : pt(pt) {} 64 Point operator [] (int x) { return pt[x];} 65 int size() { return pt.size();} 66 double area() { 67 double ret = 0.0; 68 int sz = pt.size(); 69 pt.push_back(pt[0]); 70 for (int i = 1; i <= sz; i++) ret += crossDet(pt[i], pt[i - 1]); 71 pt.pop_back(); 72 return fabs(ret / 2.0); 73 } 74 } ; 75 76 Poly halfPlane(DLine *L, int n) { 77 Poly ret = Poly(); 78 sort(L, L + n); 79 int fi, la; 80 Point *p = new Point[n]; 81 DLine *q = new DLine[n]; 82 q[fi = la = 0] = L[0]; 83 for (int i = 1; i < n; i++) { 84 while (fi < la && !onLeft(L[i], p[la - 1])) la--; 85 while (fi < la && !onLeft(L[i], p[fi])) fi++; 86 q[++la] = L[i]; 87 if (sgn(crossDet(q[la].v, q[la - 1].v)) == 0) { 88 la--; 89 if (onLeft(q[la], L[i].p)) q[la] = L[i]; 90 } 91 if (fi < la) p[la - 1] = dLineIntersect(q[la - 1], q[la]); 92 } 93 while (fi < la && !onLeft(q[fi], p[la - 1])) la--; 94 if (la <= fi) return ret; 95 p[la] = dLineIntersect(q[la], q[fi]); 96 for (int i = fi; i <= la; i++) ret.pt.push_back(p[i]); 97 return ret; 98 } 99 100 bool isClockwise(Point *pt, int n) { 101 double sum = 0.0; 102 pt[n] = pt[0]; 103 Point O = Point(0.0, 0.0); 104 for (int i = 0; i < n; i++) { 105 sum += crossDet(O, pt[i], pt[i + 1]); 106 } 107 return sum < 0; 108 } 109 110 int main() { 111 // freopen("in", "r", stdin); 112 int T, n; 113 cin >> T; 114 while (T-- && cin >> n) { 115 for (int i = 0; i < n; i++) cin >> pt[i].x >> pt[i].y; 116 pt[n] = pt[0]; 117 if (isClockwise(pt, n)) for (int i = 0; i < n; i++) dl[i] = DLine(pt[i + 1], pt[i] - pt[i + 1]).move(-EPS); 118 else for (int i = 0; i < n; i++) dl[i] = DLine(pt[i], pt[i + 1] - pt[i]).move(-EPS); 119 Poly tmp = halfPlane(dl, n); 120 if (tmp.size() > 2) puts("YES"); 121 else puts("NO"); 122 } 123 return 0; 124 } 125 126 /* 127 3 128 6 129 0 0 130 100 0 131 100 100 132 0 100 133 50 75 134 50 25 135 4 136 0 0 137 0 1 138 1 1 139 1 0 140 8 141 0 0 142 0 2 143 1 2 144 1 1 145 2 1 146 2 2 147 3 2 148 3 0 149 */
——written by Lyon