luogu P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
题面传送门
鸽了大半个月了回来补掉了这道题。
按照坐标轴排序的比极角序不知道好写多少啊。
首先按照\(x\)为第一关键字,\(y\)为第二关键字排序。
然后用叉积判断当前栈内的点和要入栈的点的位置关系,如果顺时针就弹掉。
然后这样可以构造出下凸壳。再来一遍构造上凸壳即可。
code:
#include<cstdio>
#include<cmath>
#include<algorithm>
#define I inline
#define N 100039
#define re register
#define ll long long
#define db double
using namespace std;
int n,m,k,x,y,z,sh=-1,tot=1;db ans;
struct yyy{db a,b;}f[N],st[N];
I bool cmp(yyy x,yyy y){return x.a==y.a?(x.b<y.b):(x.a<y.a);}
I db dis(yyy x,yyy y){return sqrt((x.a-y.a)*(x.a-y.a)+(x.b-y.b)*(x.b-y.b));}
I ll make(yyy x,yyy y,yyy a,yyy b){return (y.a-x.a)*(b.b-a.b)-(y.b-x.b)*(b.a-a.a);}
int main(){
freopen("1.in","r",stdin);
register int i;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%lf%lf",&f[i].a,&f[i].b);sort(f+1,f+n+1,cmp);
for(i=1;i<=n;i++){
while(sh>=1&&make(st[sh-1],st[sh],st[sh-1],f[i])<0) sh--;
st[++sh]=f[i];
}
for(i=1;i<=sh;i++) ans+=dis(st[i],st[i-1]);sh=-1;
for(i=n;i;i--){
while(sh>=1&&make(st[sh-1],st[sh],st[sh-1],f[i])<0)
sh--;
st[++sh]=f[i];
}
for(i=1;i<=sh;i++) ans+=dis(st[i],st[i-1]);printf("%.2lf\n",ans);
}