凸包是指包围原点集的最小凸多边形的顶点组成的集合。
求凸包的时间复杂度为(O(nlog n))
Graham scan算法
模板一:极角排序法
const int maxn=50010;
P ps[maxn],qs[maxn]; //ps为原点集,qs为凸包中的点集
int square_dis(P A,P B){
return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
int cmp(P A,P B){
int x=Cross(A-ps[0],B-A);
if(x>0||(x==0 && square_dis(A,ps[0])<square_dis(B,ps[0]))) return 1;
return 0;
}
int Graham(){
int k=0;
for(int i=0;i<n;i++){
if(ps[i].y<ps[k].y || (ps[i].y==ps[k].y && ps[i].x<ps[k].x)) k=i;
}
swap(ps[0],ps[k]);
sort(ps+1,ps+n,cmp);
int tot=2;
qs[0]=ps[0];
qs[1]=ps[1];
for(int i=2;i<n;i++)
{
while(tot>1 && Cross(qs[tot-1]-qs[tot-2],ps[i]-qs[tot-1])<=0) tot--;
qs[tot++]=ps[i];
}
return tot;
}
模板二:直角坐标排序法
bool cmp(P A,P B){
if(A.x!=B.x) return A.x<B.x;
return A.y<B.y;
}
vector<P> convex_hull(P* ps,int n){
sort(ps,ps+n,cmp);
int k=0;
vector<P> qs(n*2);
for(int i=0;i<n;i++){
while(k>1 && Cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<=0) k--;
qs[k++]=ps[i];
}
for(int i=n-2,t=k;i>=0;i--){
while(k>t && Cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<=0) k--;
qs[k++]=ps[i];
}
qs.resize(k-1);
return qs;
}
模板题:hdu1348 Wall