算法大体思想:形成凸包的构造函数是这样的,找到一条直线l过其中一点(记为A)并且所有其他点都在l的同侧(显然这样的直线一定可以找到),则A必为凸包上的一点。让l以A为轴点向一个方向(比如:顺时针方向)不断旋转,直到l碰到除A以外的第一个点(记为B)。如果同时碰到多于一个点,则取与A点距离最大的。再次以B为轴点,向相同的方向的旋转l,重复上述过程,直到l回到A点。
附上代码:
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int n;
struct point{
double x,y;
point(){}
point(double _x,double _y){
x=_x;y=_y;
}
point operator - (point &p){
return point(x-p.x,y-p.y);
}
}a[100051];
int p[100051];
double cross(point a,point b)
{
return a.x*b.y-a.y*b.y;
}
double dist2(point p1,point p2)
{
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}
bool judgeonleft(point p0,point p1,point p2)
{
double s=cross(p1-p0,p2-p0);
return s<0||(s==0&&(dist2(p1,p0)>=dist2(p2,p0)));
}
int main()
{
scanf("%d",&n);
int first=1;
for(int i=1;i<=n;i++){
scanf("%lf%lf",&a[i].x,&a[i].y);
if(a[i].x<a[first].x||(a[i].x==a[first].x&&a[i].y<a[first].y)){
first=i;
}
}
int top=0;
p[++top]=first;
do{
int ep=1;
for(int i=2;i<=n;i++){
if(judgeonleft(a[p[top]],a[i],a[ep])){
ep=i;
}
}
p[++top]=ep;
}while(p[top]!=first);
top--;
printf("%d\n",top);
for(int i=1;i<=top;i++){
printf("%.2f %.2f\n",a[p[i]].x,a[p[i]].y);
}
return 0;
}