这题十分特别以及极其的坑人啊,颇有一种高数的感觉——已知一个鸡蛋的重量是10g,求算地球的质量。
说的是什么呢。。话说很久很久以前有一个凸包,后来凸包上丢了一些点,问你现存的点组成的凸包还是以前的那个凸包吗。。~
这是在考什么呢?好像跟凸包有关系,但明显感觉没关系啊。
使劲YY了几下,凸包在什么情况下是不变的呢?大约是去掉的点原来就在凸包上,去掉了以后不影响凸包的边。
但是这题给的是去掉点后的凸包,也用不上啊。
又使劲YY了几下,突然茅厕顿开:如果现在凸包上每条边就有3个点,那么说明以前凸包上每条边至少有3个点,那么以前的凸包即使去掉了某些点,凸包也不会变。
想来感觉有点疑问啊,如果掉下去的点是凸包的顶点呢,那么顶点掉下去之后凸包就改变了。
但是这道题厉害就厉害在现在凸包上的点就是原来凸包点的子集,也就是说如果当初顶点掉了,新形成的边肯定是一条新的边,新的边上肯定不会有3个点的。
所以说捏,如果凸包上每条边都有3个以上的点的话,这个凸包肯定和原凸包一样,也就是说没有形成新的边。
啊呀呀,求个凸包,然后对于每一条边枚举所有的点,看在边上的点有多少个,任意一条边少于3个点的话就NO,要是每条边上都有3个以上的点的话,就YES。
饶了这么大一个圈子,弄半天就这么点事。罢了罢了、
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; #define eps 1e-8 #define X 1010 inline bool dd(double x,double y){return fabs(x-y)<eps;} inline bool dy(double x,double y){return x>y+eps;} inline bool xy(double x,double y){return x<y-eps;} inline bool dyd(double x,double y){return x>y-eps;} inline bool xyd(double x,double y){return x<y+eps;} struct point{ double x,y,z; }c[X]; inline double cp(point a,point b,point c){ return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x); } inline double disp2p(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline bool cmp(point a,point b){ double len=cp(c[0],a,b); if(dd(len,0.0)) return xy(disp2p(c[0],a),disp2p(c[0],b)); return xy(len,0.0); } int stk[X],top,n; void graham(){ int tmp=0,i; for(i=1;i<n;i++) if(xy(c[i].x,c[tmp].x)||dd(c[i].x,c[tmp].x)&&xy(c[i].y,c[tmp].y)) tmp=i; swap(c[0],c[tmp]); sort(c+1,c+n,cmp); stk[0]=0;stk[1]=1; top=1; for(i=2;i<n;i++){ while(xyd(cp(c[stk[top]],c[stk[top-1]],c[i]),0.0)&&top>=1) top--; stk[++top]=i; } } void check(){ int i,j,cnt; for(i=0;i<top;i++){ cnt=0; for(j=0;j<n;j++) if(dd(cp(c[stk[i]],c[stk[i+1]],c[j]),0.0)) cnt++; if(cnt<3){ printf("NO\n"); return ; } } printf("YES\n"); } int main(){ int i,j,t; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=0;i<n;i++) scanf("%lf%lf",&c[i].x,&c[i].y); if(n<6){ printf("NO\n"); continue; } graham(); check(); } return 0; }