pku 1228 Grandpa's Estate(判断直线上顶点个数)

题意:有一个凸包,给定这个凸包上的部分顶点,问这些顶点能否唯一确定这个凸包。

 

当由这部分顶点构成的凸包的每条边上都有至少三个顶点的时候,可以唯一确定这个凸包。至于为什么,自己画图得到^_^。

 

已知这部分顶点都是凸包上的顶点。按照常规的寻找凸包的方法,将所有顶点根据和起始节点的角度排序,这即是顶点在凸包上出现的顺序。于是我们只要从前往后扫描这些点,即可得到每条边上的点的数量,判断点是否共线可直接用向量叉积。其中需要指出的是,最后一条边上的点的排列是逆着的,需要特殊处理。

#include <iostream> using namespace std; struct Node { int x,y; }pt[1005]; int Distance(Node& p1,Node& p2) { return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y); } int CrossMutiply(Node& p1,Node& p2,Node& p3) { return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x); } int CMP(const void* a,const void* b) { int m=CrossMutiply(pt[0],*((Node*)a),*((Node*)b)); if(m==0) return Distance(*(Node*)a,pt[0])-Distance(pt[0],*(Node*)b); else return -m; } bool Check(int n) { if(n<6) return false; int swap=0; for(int i=1;i<n;i++) { if(pt[i].y<pt[swap].y||(pt[i].y==pt[swap].y&&pt[i].x<pt[swap].x)) swap=i; } Node temp=pt[0]; pt[0]=pt[swap]; pt[swap]=temp; qsort(pt+1,n-1,sizeof(pt[0]),CMP); int point_cnt=2; int last_point=n-1; pt[n]=pt[0]; while(last_point>=0&&0==CrossMutiply(pt[last_point-1],pt[last_point],pt[last_point+1])) last_point--; if(last_point<0||last_point==n-1) return false;//所有点共线和最后一条边上只有两个点 则不满足条件 pt[last_point]=pt[n-1]; for(int i=2;i<=last_point;i++) { if(CrossMutiply(pt[i-2],pt[i-1],pt[i])==0) point_cnt++; else { if(point_cnt<3) return false; point_cnt=2; } } } int main() { int t=0; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d%d",&pt[i].x,&pt[i].y); } if(Check(n)) printf("YES/n"); else printf("NO/n"); } return 0; }

你可能感兴趣的:(pku 1228 Grandpa's Estate(判断直线上顶点个数))