凸包就是給你一堆點,再給你一根繩子你用這個繩子把這堆點圍起來!繩子與這些點所接觸的點叫做凸包點,圍成的圖形叫做凸包!
具體講解看這裏here
下面是我個人的板子,做了好多題的磨練證明我的板子是可以帶出門的
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int n,tot;///n爲二維平面上點的個數,tot爲凸包上點的個數
struct Point
{
int x,y;
Point(double x=0,double y=0):x(x),y(y){}
}a[10009],p[10009];///p[]用來儲存凸包
typedef Point Vector;
Vector operator -(Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
double dis(Point a,Point b)///距離此處沒有進行開平方!!!!!!!!!
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double Wai(Point p0,Point p1,Point p2) ///判斷向量p2是否在p0,p1的左邊是返回正值其他相反
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int cmp(Point p1,Point p2)///極角排序;
{
int x=Wai(p1,p2,a[0]);
if(x>0||(x==0&&dis(p1,a[0])<dis(p2,a[0]))) return 1;
return 0;
}
void Graham()
{
int k=0;
for(int i=0;i<n;i++)
if(a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x)) k=i;
swap(a[0],a[k]);
sort(a+1,a+n,cmp);
tot=2,p[0]=a[0],p[1]=a[1];
for(int i=2;i<n;i++)
{
while(tot>1&&Wai(p[tot-1],p[tot-2],a[i])>=0) tot--;
p[tot++]=a[i];
}
}
double c()///輸出周長
{
double dist=0;
for(int i=0;i<tot-1;i++)
{
dist+=sqrt(dis(p[i],p[i+1]));
}
dist+=sqrt(dis(p[tot-1],p[0]));
return dist;
}
double s()///輸出面積
{
double ss=0;
for(int i=1;i<tot-1;i++)
{
ss+=(Wai(p[0],p[i],p[i+1])/2);
}
return ss;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i].x>>a[i].y;
Graham();
for(int i=0;i<tot;i++)
cout<<p[i].x<<" "<<p[i].y<<endl;
return 0;
}
/*
5
0 0
2 0
2 1
1 1
0 1
*/