[nyoj78]圈水池(凸包入門)
阿新 • • 發佈:2019-01-31
#include<stdio.h> #include<math.h> #include<stdlib.h> #include<algorithm> using namespace std; struct Point{ double x,y; Point(double x=0,double y=0):x(x),y(y){ } }p[110],ch[110]; typedef Point Vector;//定義Point的別名 //對自定義的結構體進行運算子過載 Vector operator - (Vector A,Vector B){ return Vector(A.x-B.x,A.y-B.y); } Vector operator * (Vector A,double p){ return Vector(A.x*p,A.y*p); } bool operator < (const Point &A,const Point &B){ return A.x<B.x||(A.x==B.x&&A.y<B.y);//先比較x,如果x相同接著比較y } //計算叉積 double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x; } void Andrew(Vector *p,int n,Vector *ch){ sort(p,p+n);//對點從小到大排序 //凸包下部分 int 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--;//這裡的m>1是確保凸包集合中至少存在一個向量 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]; } sort(ch,ch+m); for(int i=0;i<m;i++) { printf("%.0f %.0f\n",ch[i].x,ch[i].y); } } int main() { int t; int n; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) { int a,b; scanf("%d%d",&a,&b); p[i].x=a; p[i].y=b; } Andrew(p,n,ch); } return 0; }