/* 凸包: 1.选取最左下边的点p0 2.根据剩余的m点集Q相对p0的极角排序,如果极角相同,只考虑最远的点 3.对堆栈进行初始化 push(p0,S) push(p1,S) push(p2,S) for i=3 to m do the angle formed by points next_to_top(s) top(s) and pi make a nonleft turn do pop(S) PUSH(pi,S) return S */ /* struct point { double x,y; }; bool mult(point p0,point p1,point p2) { return (p1.x-p0.x)*(p2.y-p0.y)>=(p2.x-p0.x)*(p1.y-p0.y); } bool operator<(const point &p1,const point &p2) { return p1.y<p2.y||(p1.y==p2.y&&p1.x<p2.x); } int graham(point pnt[],int n,point res[])//pnt是图中的所有的点,res是通过判断后在凸边行边上的点, //而且这些点都是按逆时针存储的,n是所有点的个数。 { int i,len,k=0,top=1; sort(pnt, pnt + n); if(n==0) return 0; res[0]=pnt[0]; if(n==1) return 1; res[1]=pnt[1]; if(n==2) return 2; res[2]=pnt[2]; for(i=2;i<n;i++) { while(top&&mult(pnt[i],res[top],res[top-1])) top--; res[++top]=pnt[i]; } len=top;res[++top]=pnt[n-2]; for(i=n-3;i>=0;i--) { while(top!=len&&mult(pnt[i],res[top],res[top-1])) top--; res[++top]=pnt[i]; } return top; // 返回凸包中点的个数 } 例题1:nyist 圈水池(求凸包中的每个顶点-凸包的简单应用) 描述 有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水,各个水池都标有各自的坐标,现在要你写一个程序利用最短的篱笆将这些供水装置圈起来!(篱笆足够多,并且长度可变) 输入 第一行输入的是N,代表用N组测试数据(1<=N<=10),第二行输入的是m,代表本组测试数据共有m个供水装置(3<=m<=100)接下来m行代表的是各个供水装置的横纵坐标 输出 输出各个篱笆经过各个供水装置的坐标点,并且按照x轴坐标值从小到大输出,如果x轴坐标值相同,再安照y轴坐标值从小到大输出 样例输入 1 4 0 0 1 1 2 3 3 0 样例输出 0 0 2 3 3 0 code: */ #include<iostream> #include<algorithm> #include<cmath> using namespace std; const double EPS = 1E-6; struct point { int x,y; }; point p[105],res[105]; double Dist(const point &arg1, const point &arg2) { return sqrt( (arg1.x - arg2.x)*(arg1.x - arg2.x) + (arg1.y - arg2.y)*(arg1.y - arg2.y) ); } bool multi(point p0,point p1,point p2) { return (p1.x-p0.x)*(p2.y-p0.y)>(p2.x-p0.x)*(p1.y-p0.y); } int mysort1(point a,point b) { if(a.y!=b.y) return a.y<b.y; if(a.y==b.y&&a.x!=b.x) return a.x<b.x; } bool cmp(const point &a,const point &b) { point temp=p[0]; double xmt=(a.x-temp.x)*(b.y-temp.y)-(b.x-temp.x)*(a.y-temp.y); if(xmt) //向量不共线就按逆时针旋转 return xmt>0; return Dist(a,temp)>Dist(b,temp);//向量共线取最长的。 } int main() { int n,k,len; cin>>k; while(k--) { cin>>n; for(int i=0;i<n;i++) cin>>p[i].x>>p[i].y; sort(p,p+n,mysort1);//排序,找到最左下角的点 res[0]=p[0]; sort(p+1,p+n,cmp);//按照极角排序 res[1]=p[1]; res[2]=p[2]; int top=2; for(int i=3;i<n;i++) { while(multi(p[i],res[top],res[top-1])) top--; res[++top]=p[i]; } for(int i=0;i<=top;i++) cout<<res[i].x<<" "<<res[i].y<<endl; } system("pause"); return 0; }