cogs炸了,所以暂没有题面。
最基础的板子,因为根据点从左到右,横轴相同纵轴从下到上的顺序排了序,正向一遍求下壳(念什么?qiao:ke)再翻一遍求上壳,出入栈的原理就是根据叉乘逆时针为正,顺时针为负来判断是否外凸。想不明白可以画下图。
剩下就是扔个板子了。
#define e 1e-8
#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int n;
struct vec
{
double x,y;
inline friend bool operator < (vec a,vec b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
inline friend vec operator -(vec a,vec b)
{
return (vec){a.x-b.x,a.y-b.y};
}
} a[10005];
int zhan[10005],head=0,vis[10005];
double ans=0;
vector<vec> hh;
double S(vec a,vec b)
{
return a.x*b.y-b.x*a.y;
}
bool check(vec a,vec b,vec c)
{
return S(b-a,c-a)>e;
}
double pf(double x)
{
return x*x;
}
double jl(vec a,vec b)
{
return sqrt(pf(a.x-b.x)+pf(a.y-b.y));
}
int yjn()
{
// freopen("fc.in","r",stdin);
// freopen("fc.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
sort(a+1,a+n+1);
zhan[++head]=1;zhan[++head]=2;
for(int i=3;i<=n;i++)
{
while(head>1&&!check(a[zhan[head]],a[i],a[zhan[head-1]]))head--;
zhan[++head]=i;
}
for(int i=1;i<=head;i++)vis[zhan[i]]=1,hh.push_back(a[zhan[i]]);
head=0;
zhan[++head]=n;
zhan[++head]=n-1;
for(int i=n-2;i>=1;i--)
{
while(head>1&&check(a[zhan[head]],a[zhan[head-1]],a[i]))head--;
zhan[++head]=i;
}
for(int i=1;i<=head;i++)if(!vis[zhan[i]])hh.push_back(a[zhan[i]]),vis[zhan[i]]=1;
for(int i=0,s=hh.size();i<s;i++)
ans+=jl(hh[i],hh[(i+1)%s]);
printf("%.2lf",ans);
}
int qty=yjn();
int main(){;}