Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 11508 | Accepted: 3188 |
Description
Input
Output
Sample Input
1 6 0 0 1 2 3 4 2 0 2 4 5 0
Sample Output
NO
Source
题意:输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点,得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点。
题解:凸包的每条边包含端点至少有3个点时时稳定凸包。我们只需判断凸包的每条边是否存在剩下的点在边上。
#include<cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<vector> #define INF 0x3f3f3f3f #define _sign(x) ((x)>eps?1:((x)<-eps?2:0)) using namespace std; const int MAXN = 1030; 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); } //叉积 double operator ^(const Point &b)const { return x*b.y - y*b.x; } //点积 double operator *(const Point &b)const { return x*b.x + y*b.y; } //绕原点旋转角度B(弧度值),后x,y的变化 void transXY(double B) { double tx = x,ty = y; x = tx*cos(B) - ty*sin(B); y = tx*sin(B) + ty*cos(B); } }; Point L[MAXN]; int Stack[MAXN],top; int n; double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double multi(Point p1, Point p2, Point p3) { return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x); } int sgn(double x) { if(fabs(x)<1e-12)return 0; if(x<0)return -1; return 1; } //相对于L[0]的极角排序 bool _cmp(Point p1,Point p2) { double tmp =(p1-L[0])^(p2-L[0]); if(sgn(tmp)>0)return true; else if(sgn(tmp)==0&&sgn(dist(p1,L[0])-dist(p2,L[0]))<= 0) return true; else return false; } void Graham(int m) { if(m<=1)return; Point p0; int k = 0; p0 = L[0]; //找最下边的一个点 for(int i=1; i<m; i++) { if((p0.y>L[i].y)||(p0.y==L[i].y&&p0.x>L[i].x)) { p0 = L[i]; k = i; } } swap(L[k],L[0]); sort(L+1,L+m,_cmp); if(m==1) { top=1,Stack[0] = 0; return; } if(m==2) { top=2,Stack[0]=0,Stack[1]=1; return ; } Stack[0]=0; Stack[1]=1; top=2; for(int i=2; i<m; i++) { while(top>1&&sgn((L[Stack[top-1]]-L[Stack[top-2]])^(L[i]-L[Stack[top-2]]))<=0) top--; Stack[top++] = i; } } int main() { //freopen("test.in","r",stdin); int t; cin>>t; while(t--) { scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%lf%lf",&L[i].x,&L[i].y); } if(n<6) { printf("NO\n"); continue; } Graham(n); bool flag=1; for(int i=0; i<top; i++) { int u=Stack[i],v=Stack[(i+1)%top]; flag=1; ///判断剩下的点是否存在至少一点在边上 for(int j=0; j<n; j++) { if(j==u||j==v)continue; if(multi(L[u],L[j],L[v])==0) { flag=0; break; } } if(flag)break; } printf("%s\n",flag==0?"YES":"NO"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/acm_baihuzi/article/details/47430735