前置知识
极角排序:按向量与\(x\)轴的极角排序,\(\theta\in [0,2\pi]\)。
向量差集:\(\vec a\times\vec b=x_ay_b-x_by_a\),可以发现极角排序中若\(\vec a\lt \vec b,\vec a\times \vec b\gt 0\) 。
凸包
先找到所有点中最下面的点,多个最下面则取最左边。
然后按照这个点为原点\(O\),对其它点\(P\)的向量\(\overrightarrow {OP}\)极角排序。排序后呈现类似扇形顺序。
然后每次按顺序丢入点\(p_i\),\(p_i\)和凸包内前一个点形成的向量\(\overrightarrow {p_ip_{i-1}}\),若\(\overrightarrow {p_ip_{i-1}}\times \overrightarrow {p_{i-1}p_{i-2}}>0\),说明\(p_{i-1}\)成凹陷进去的一个顶点了,于是把\(p_{i-1}\)删除。依次这样添加即可。
模板题:P2742
#include <bits/stdc++.h> using namespace std; const double eps=1e-8; const double pi = acos(-1.0); const int MAXN=10005; int n,cnt; struct vec { double x=0.0,y=0.0; int id=0; vec(double X=0,double Y=0,int ID=0){ x=X,y=Y,id=ID; } }p[MAXN],o,ax[MAXN];//Point : X (x,y) , O (x,y) ; Vector : AX_id (x,y) vec operator + (vec aa,vec bb){ return (vec){aa.x+bb.x, aa.x+bb.y,0}; } vec operator - (const vec &aa,const vec &bb){return (vec){aa.x-bb.x,aa.y-bb.y,0};} double operator * (const vec &aa,const vec &bb){return aa.x*bb.x+aa.y*bb.y;} double operator ^ (const vec &aa,const vec &bb){return aa.x*bb.y-aa.y*bb.x;} vec operator * (const double bb,const vec &aa){return (vec){bb*aa.x,bb*aa.y,aa.id};} vec rotate (vec aa,double bb){ return (vec){cos(bb)*aa.x-sin(bb)*aa.y,sin(bb)*aa.x+cos(bb)*aa.y,aa.id}; } double dis(const vec &aa){ return sqrt(aa.x*aa.x+aa.y*aa.y); } bool cmp (const vec &aa,const vec &bb){//Sort the vector AX_i if(fabs(aa^bb) > eps)return (aa^bb) > eps; else { return fabs(aa.x)<fabs(bb.x); } } stack <vec> st; stack <vec> pt; int main(){ o.x=1e17,o.y=1e17; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf%lf",&p[i].x,&p[i].y); p[i].id=i; if(p[i].y<o.y-eps)o.y=p[i].y,o.x=p[i].x,o.id=i; if(fabs(p[i].y-o.y)<=eps&&p[i].x<o.x)o.y=p[i].y,o.x=p[i].x,o.id=i; } for(int i=1;i<=n;i++){ if(i==o.id)continue; cnt++; ax[cnt]=p[i]-p[o.id]; ax[cnt].id=i; } sort(ax+1,ax+1+cnt,cmp); st.push(p[ax[1].id]-p[o.id]); pt.push(p[o.id]);pt.push(p[ax[1].id]); for(int i=2;i<=cnt;i++){ while(!st.empty()&&((p[ax[i].id]-pt.top())^(st.top()))>=-eps) st.pop(),pt.pop(); st.push(p[ax[i].id]-pt.top()); pt.push(p[ax[i].id]); } double ans=0.0; while(!st.empty()){ ans+=dis(st.top()); st.pop(); } ans+=dis((vec){pt.top()-p[o.id]}); printf("%.2f\n",ans); return 0; }