Graham 算法
O
(
n
∗
l
o
g
n
)
O(n*logn)
O(n∗logn)
求得凸包点按逆时针转
Template
int dcmp(double x, double y){
if(fabs(x - y) < eps)
return 0;
if(x > y)
return 1;
return -1;
}
struct Point{
double x,y;
Point(double x = 0,double y = 0):x(x),y(y){ } // 构造函数
bool operator < (const Point&B)const{return y < B.y || y == B.y && x < B.x;}
};
double Length(Vector A) {return sqrt(Dot(A,A));}
// 点积 夹角与点积的关系
double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
// 叉积
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
// 极角排序 叉乘实现
bool cmp(Point a,Point b){
double t = Cross(a-p[1],b-p[1]);
if(sgn(t) > 0) return true;
if(sgn(t) == 0 && dcmp(Length(a-p[1]),Length(b-p[1])) < 0) return true;
return false;
}
void Graham(){
sort(p+1,p+1+n);// 重载小于< 运算符找到最左下角的点
sort(p+2,p+1+n,cmp);
stk[++top] = 1,stk[++top] = 2;
forr(i,3,n){
while(top >=2 && sgn(Cross(p[stk[top]]-p[stk[top-1]],p[i] - p[stk[top-1]])) <= 0) top--; // < 共线加入凸包
stk[++top] = i;
}
}
Andrew 算法
O
(
n
∗
l
o
g
n
)
O(n*logn)
O(n∗logn)
不需要极角排序较优
注意 访问凸包要通过
s
t
k
stk
stk 吃过一次亏
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
// 点 c 是否在向量ab的左边
// >= 共线不加入凸包
bool ToLeftTest(Point a,Point b,Point c){return Cross(b-a,c-a) > 0;}
int stk[1005];
bool used[1005];
void Andrew(){
sort(p+1,p+1+n);
int top = 0;
forr(i,1,n){
while(top >= 2 && ToLeftTest(p[stk[top-1]],p[stk[top]],p[i])) used[stk[top--]] = 0;
stk[++top] = i;
used[i] = 1;
}
used[1] = 0;
for(int i = n;i;i--){
if(used[i]) continue;
while(top >= 2 && ToLeftTest(p[stk[top-1]],p[stk[top]],p[i])) top--;
stk[++top] = i;
}
}
例题
int n;
Point p[100005];
int stk[100005],top;
struct Point{
double x,y;
Point(double x = 0,double y = 0):x(x),y(y){ } // 构造函数
bool operator < (const Point&B)const{return y < B.y || y == B.y && x < B.x;}
};
bool cmp(Point a,Point b){
double t = Cross(a-p[1],b-p[1]);
if(sgn(t) > 0) return true;
if(sgn(t) == 0 && dcmp(Length(a-p[1]),Length(b-p[1])) < 0) return true;
return false;
}
void Graham(){
sort(p+2,p+1+n,cmp);
stk[++top] = 1,stk[++top] = 2;
forr(i,3,n){
while(top >=2 && sgn(Cross(p[stk[top]]-p[stk[top-1]],p[i] - p[stk[top-1]])) <= 0) top--;
stk[++top] = i;
}
}
signed main()
{
cin>>n;
forr(i,1,n)cin >> p[i].x >> p[i].y;
sort(p+1,p+1+n);
Graham();
double are = 0;
forr(i,2,top-1){
are += Cross(p[stk[i]]-p[1],p[stk[i+1]]-p[1])/2.0;
}
are = fabs(are/50.0);
printf("%.0f\n",floor(are));
return 0;
}