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 }
View Code

 

posted @ 2013-11-09 20:40  Oyking  阅读(308)  评论(0编辑  收藏  举报