Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 9642 | Accepted: 2606 |
Description
Input
Output
Sample Input
1 6 0 0 1 2 3 4 2 0 2 4 5 0
Sample Output
NO
Source
Posted by proverbs at 2013-02-24 10:28:09 on Problem 1228 Input: 4 6 1 1 2 2 3 3 4 4 5 5 6 6 1 1 1 8 0 0 0 1 0 2 0 3 1 1 2 2 3 3 2 3 8 0 0 0 2 1 0 1 2 2 2 3 0 3 1 3 2 Output: NO NO YES NO
1228 | Accepted | 756K | 0MS | G++ | 2662B | 2013-08-22 20:32:28 |
#include<stdio.h> #include<math.h> #include<algorithm> #include<iostream> using namespace std; const int maxn = 1000+10; int n,m; struct Point { double x,y; Point() {} Point(double _x, double _y) { x = _x; y = _y; } Point operator - (const Point &b) const { return Point(x-b.x, y-b.y); } }p[maxn], ch[maxn]; //高精度判断 const double eps = 1e-5; int dcmp(double x) { if(x < eps) return 0; else return x < 0 ? -1 : 1; } double Cross(Point a, Point b) { //叉积 return a.x*b.y - a.y*b.x; } double Dot(Point a, Point b) { //点积 return a.x*b.x + a.y*b.y; } bool cmp(Point a, Point b) { return (a.x == b.x && a.y < b.y) || a.x < b.x; } //为判定是否为稳定凸包, 求凸包时保存共线的点,叉积时去掉 = void ConvexHull(Point *p, int n, Point *ch) { sort(p, p+n, cmp); m = 0; for(int i = 0; i < n; i++) { while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--; ch[m++] = p[i]; } int k = m; for(int i = n-2; i >= 0; i--) { while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--; ch[m++] = p[i]; } if(n > 1) m--; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); double x,y; for(int i = 0; i < n; i++) { scanf("%lf%lf", &x, &y); p[i] = Point(x, y); } if(n < 6) { //如果开始的点少于 6 个肯定不行 printf("NO\n"); continue; } ConvexHull(p, n, ch); if(m < 6) { //如果凸包的点少于 6 个肯定不行 printf("NO\n"); continue; } //排除凸包上的所有的点共线的情况 //注意:下面的点用凸包上的点ch[], 不小心写错成了 p[] 贡献了两次 WA int flag = 1; for(int i = 0; i < m-1; i++) { double c = Cross(ch[i+1]-ch[i], ch[(i+2)%m]-ch[i+1]); if(dcmp(c) != 0) { //说明现有的点不共线, 暂且合法 flag = 0; break; } } if(flag == 1) { printf("NO\n"); continue; } //判断凸包是否稳定:即每条边都至少有三个点 flag = 1; ch[m] = ch[0]; for(int i = 0; i < m-1;) { //printf("test i = %d\n", i); //此处的 i 是凸包每条边的第一个点, 可能不包含最后一条边。。。 double c = Cross(ch[i+1]-ch[i], ch[(i+2)%m]-ch[i+1]); if(dcmp(c != 0)) { //printf("erro: i =%d, c = %.0lf\n", i, c); flag = 0; break; } while(c == 0 && i < m-1) { //走到当前边的尽头 i++; c = Cross(ch[i+1]-ch[i], ch[(i+2)%m]-ch[i+1]); } i++; //下一条边起点的编号 } if(flag) { //判断最后一条边是否固定。。。 double c = Cross(ch[m]-ch[m-1], ch[m-1]-ch[m-2]); if(c != 0) flag = 0; } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }