题链:
http://poj.org/problem?id=1228
题解:
计算几何,凸包
题意:给出一些点,求出其凸包,问是否是一个稳定的凸包。
稳定凸包:不能通过新加点使得原来凸包上的点(包括原来凸包的边的点和顶点上的点)仍然都在形成的新凸包上。
其实就是问是否在凸包的每条边上都至少有1个点。
(显然,如果有一条边上没有点,那么可以在这条边的外侧添加一个点使得凸包变大,即不稳定。)
所以就求出一个凸包,并保留下凸包边上的点,然后判断是否存在某一条边上没有点,(即判断有没有连续的拐角就好了)。
(另外还需要判断一下整个凸包是否为一条线,如果是一条线的话显然应该输入"NO"。)
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 1050 using namespace std; const double eps=1e-8; int sign(double x){ if(fabs(x)<=eps) return 0; return x<0?-1:1; } struct Point{ double x,y; Point(double _x=0,double _y=0):x(_x),y(_y){} void Read(){scanf("%lf%lf",&x,&y);} }; typedef Point Vector; bool operator < (Point A,Point B){return sign(A.x-B.x)<0||(sign(A.x-B.x)==0&&sign(A.y-B.y)<0);} bool operator == (Point A,Point B){return sign(A.x-B.x)==0&&sign(A.y-B.y)==0;} Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);} double operator ^ (Point A,Point B){return A.x*B.y-A.y*B.x;} Point D[MAXN],H[MAXN]; int _Andrew(int dnt){ int hnt=0,k=0; sort(D+1,D+dnt+1); dnt=unique(D+1,D+dnt+1)-D-1; for(int i=1;i<=dnt;i++){ while(hnt>1&&sign((H[hnt]-H[hnt-1])^(D[i]-H[hnt-1]))<0) hnt--; H[++hnt]=D[i]; } k=hnt; for(int i=dnt-1;i>=1;i--){ while(hnt>k&&sign((H[hnt]-H[hnt-1])^(D[i]-H[hnt-1]))<0) hnt--; H[++hnt]=D[i]; } if(dnt>1) hnt--; return hnt; } bool Judge(int hnt){ bool turn=0,a,b; for(int h,i=2,j,k;i<=hnt;i++){ h=i-1; j=(i)%hnt+1; k=(i+1)%hnt+1; a=sign((H[j]-H[i])^(H[i]-H[h])); b=sign((H[k]-H[j])^(H[j]-H[i])); if(a!=0&&b!=0) return false; if(a!=0||b!=0) turn=1; } return turn; } int main(){ int N,Case; scanf("%d",&Case); while(Case--){ scanf("%d",&N); for(int i=1;i<=N;i++) D[i].Read(); N=_Andrew(N); if(Judge(N)) puts("YES"); else puts("NO"); } return 0; }