POJ 1228 Grandpa's Estate(凸包唯一性判断)
Description
Being the only living descendant of his grandfather, Kamran the Believer inherited all of the grandpa's belongings. The most valuable one was a piece of convex polygon shaped farm in the grandpa's birth village. The farm was originally separated from the neighboring farms by a thick rope hooked to some spikes (big nails) placed on the boundary of the polygon. But, when Kamran went to visit his farm, he noticed that the rope and some spikes are missing. Your task is to write a program to help Kamran decide whether the boundary of his farm can be exactly determined only by the remaining spikes.
Input
The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains an integer n (1 <= n <= 1000) which is the number of remaining spikes. Next, there are n lines, one line per spike, each containing a pair of integers which are x and y coordinates of the spike.
Output
There should be one output line per test case containing YES or NO depending on whether the boundary of the farm can be uniquely determined from the input.
题目大意:原本有一个凸多边形,现在我们不知道它的边,它的一部分点也有可能消失了,问用剩下的点能不能确定那个多边形。
思路:先求个凸包,然后判断是否凸包相邻的两点之间都存在一个题目给出的点使得这个点在这条边上。
因为有一个点在这个边上呢,这条边就确定下来了。
嘛其实没有这么麻烦,因为我在做模板所以……
啊,对了,全部点是一条直线的时候输出NO,我上了求多边形面积的模板←_←
代码(0MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 8 const int MAXN = 1010; 9 const double EPS = 1e-8; 10 const double PI = acos(-1.0);//3.14159265358979323846 11 12 inline int sgn(double x) { 13 return (x > EPS) - (x < -EPS); 14 } 15 16 struct Point { 17 double x, y; 18 Point() {} 19 Point(double x, double y): x(x), y(y) {} 20 void read() { 21 scanf("%lf%lf", &x, &y); 22 } 23 bool operator == (const Point &rhs) const { 24 return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0; 25 } 26 bool operator < (const Point &rhs) const { 27 if(y != rhs.y) return y < rhs.y; 28 return x < rhs.x; 29 } 30 Point operator + (const Point &rhs) const { 31 return Point(x + rhs.x, y + rhs.y); 32 } 33 Point operator - (const Point &rhs) const { 34 return Point(x - rhs.x, y - rhs.y); 35 } 36 Point operator * (const int &b) const { 37 return Point(x * b, y * b); 38 } 39 Point operator / (const int &b) const { 40 return Point(x / b, y / b); 41 } 42 double length() const { 43 return sqrt(x * x + y * y); 44 } 45 Point unit() const { 46 return *this / length(); 47 } 48 }; 49 typedef Point Vector; 50 51 double dist(const Point &a, const Point &b) { 52 return (a - b).length(); 53 } 54 55 double cross(const Point &a, const Point &b) { 56 return a.x * b.y - a.y * b.x; 57 } 58 //ret >= 0 means turn left 59 double cross(const Point &sp, const Point &ed, const Point &op) { 60 return sgn(cross(sp - op, ed - op)); 61 } 62 63 double area(const Point& a, const Point &b, const Point &c) { 64 return fabs(cross(a - c, b - c)) / 2; 65 } 66 67 struct Seg { 68 Point st, ed; 69 Seg() {} 70 Seg(Point st, Point ed): st(st), ed(ed) {} 71 void read() { 72 st.read(); ed.read(); 73 } 74 }; 75 typedef Seg Line; 76 77 bool isOnSeg(const Seg &s, const Point &p) { 78 return (p == s.st || p == s.ed) || 79 (((p.x - s.st.x) * (p.x - s.ed.x) < 0 || 80 (p.y - s.st.y) * (p.y - s.ed.y) < 0) && 81 sgn(cross(s.ed, p, s.st) == 0)); 82 } 83 84 bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) { 85 return (max(s1.x, e1.x) >= min(s2.x, e2.x)) && 86 (max(s2.x, e2.x) >= min(s1.x, e1.x)) && 87 (max(s1.y, e1.y) >= min(s2.y, e2.y)) && 88 (max(s2.y, e2.y) >= min(s1.y, e1.y)) && 89 (cross(s2, e1, s1) * cross(e1, e2, s1) >= 0) && 90 (cross(s1, e2, s2) * cross(e2, e1, s2) >= 0); 91 } 92 93 bool isIntersected(const Seg &a, const Seg &b) { 94 return isIntersected(a.st, a.ed, b.st, b.ed); 95 } 96 97 bool isParallel(const Seg &a, const Seg &b) { 98 return sgn(cross(a.ed - a.st, b.ed - b.st)) == 0; 99 } 100 101 //return Ax + By + C =0 's A, B, C 102 void Coefficient(const Line &L, double &A, double &B, double &C) { 103 A = L.ed.y - L.st.y; 104 B = L.st.x - L.ed.x; 105 C = L.ed.x * L.st.y - L.st.x * L.ed.y; 106 } 107 108 Point intersection(const Line &a, const Line &b) { 109 double A1, B1, C1; 110 double A2, B2, C2; 111 Coefficient(a, A1, B1, C1); 112 Coefficient(b, A2, B2, C2); 113 Point I; 114 I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1); 115 I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1); 116 return I; 117 } 118 119 bool isEqual(const Line &a, const Line &b) { 120 double A1, B1, C1; 121 double A2, B2, C2; 122 Coefficient(a, A1, B1, C1); 123 Coefficient(b, A2, B2, C2); 124 return sgn(A1 * B2 - A2 * B1) == 0 && sgn(A1 * C2 - A2 * C1) == 0 && sgn(B1 * C2 - B2 * C1) == 0; 125 } 126 127 struct Poly { 128 int n; 129 Point p[MAXN];//p[n] = p[0] 130 void init(Point *pp, int nn) { 131 n = nn; 132 for(int i = 0; i < n; ++i) p[i] = pp[i]; 133 p[n] = p[0]; 134 } 135 double area() { 136 if(n < 3) return 0; 137 double s = p[0].y * (p[n - 1].x - p[1].x); 138 for(int i = 1; i < n; ++i) 139 s += p[i].y * (p[i - 1].x - p[i + 1].x); 140 return s / 2; 141 } 142 }; 143 144 void Graham_scan(Point *p, int n, int *stk, int &top) { 145 sort(p, p + n); 146 top = 1; 147 stk[0] = 0; stk[1] = 1; 148 for(int i = 2; i < n; ++i) { 149 while(top && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top; 150 stk[++top] = i; 151 } 152 int len = top; 153 stk[++top] = n - 2; 154 for(int i = n - 3; i >= 0; --i) { 155 while(top != len && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top; 156 stk[++top] = i; 157 } 158 } 159 160 /*******************************************************************************************/ 161 162 Point p[MAXN]; 163 Poly poly; 164 int stk[MAXN], top; 165 int n, T; 166 167 bool check() { 168 poly.n = top; 169 for(int i = 0; i < top; ++i) poly.p[i] = p[stk[i]]; 170 poly.p[poly.n] = poly.p[0]; 171 if(sgn(poly.area()) == 0) return false; 172 for(int i = 0; i < poly.n; ++i) { 173 bool flag = false; 174 for(int j = 0; j < n; ++j) { 175 if(p[j] == poly.p[i] || p[j] == poly.p[i + 1]) continue; 176 if(isOnSeg(Seg(poly.p[i], poly.p[i + 1]), p[j])) { 177 flag = true; 178 break; 179 } 180 } 181 if(!flag) return false; 182 } 183 return true; 184 } 185 186 int main() { 187 scanf("%d", &T); 188 while(T--) { 189 scanf("%d", &n); 190 for(int i = 0; i < n; ++i) p[i].read(); 191 Graham_scan(p, n, stk, top); 192 if(check()) puts("YES"); 193 else puts("NO"); 194 } 195 }