思路
1. 先找到左下角点,根据该点给其他点按极角排序
bool cmp(Pdb x,Pdb y) //按极角排序
{
DB b=atan2(x.se-a[1].se,x.fi-a[1].fi);
DB c=atan2(y.se-a[1].se,y.fi-a[1].fi);
if(b!=c) return b<c;
if(x.fi!=y.fi) return x.fi<y.fi;
return x.se<y.se;
}
2. 将前两个先加入栈中,对后面每个,根据叉积判断当前栈顶两个点和正在处理的点是否构成凸包。不断弹出栈顶,最后得到栈中凸包点集
代码
P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
#include<bits/stdc++.h>
#define DB double
#define Pdb pair<double,double>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
using namespace std;
const int N=1e5+9;
int n;
DB ans;
Pdb a[N],s[N];
bool cmp(Pdb x,Pdb y) //按极角排序
{
DB b=atan2(x.se-a[1].se,x.fi-a[1].fi);
DB c=atan2(y.se-a[1].se,y.fi-a[1].fi);
if(b!=c) return b<c;
if(x.fi!=y.fi) return x.fi<y.fi;
return x.se<y.se;
}
bool CJ(Pdb x,Pdb y,Pdb z) //叉积
{
return (y.fi-x.fi)*(z.se-x.se)-(y.se-x.se)*(z.fi-x.fi)<0;
}
DB Dis(Pdb x,Pdb y)
{
return sqrt((x.fi-y.fi)*(x.fi-y.fi)+(x.se-y.se)*(x.se-y.se));
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
DB x,y;
cin>>x>>y;
a[i]=mp(x,y);
}
for(int i=2;i<=n;i++) //找到左下角点
if(a[i].fi<a[1].fi||(a[i].fi==a[1].fi&&a[i].se<a[1].se))
swap(a[1],a[i]);
sort(a+1+1,a+1+n,cmp);
int k=0,top=0;
s[++top]=a[++k]; s[++top]=a[++k]; k++;
while(k<=n)
{
if(CJ(s[top-1],s[top],a[k])) top--;
else s[++top]=a[k++];
}
s[++top]=a[1];
for(int i=2;i<=top;i++)
ans+=Dis(s[i-1],s[i]);
printf("%.2lf\n",ans);
return 0;
}