计算几何……不会啊
我们定义 (x)(y) 的叉积是 (|x||y| sin)
用坐标表示就是 (x1y2-x2y1)
根据叉积可以判断两个的夹角
然后维护一个上凸壳和下凸壳,就可以求出凸包的周长了。
// by Isaunoya
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct io {
char buf[1 << 25 | 3], *s;
int f;
io() { f = 0, buf[fread(s = buf, 1, 1 << 25, stdin)] = '
'; }
io& operator >> (int&x) {
for(x = f = 0; !isdigit(*s); ++s) f |= *s == '-';
while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
return x = f ? -x : x, *this;
}
};
struct io_out {
char buf[1 << 25 | 3], *s = buf;
~io_out() { fwrite(buf, 1, s - buf, stdout); }
void write(int x) { if(x > 9) write(x / 10); *s++ = x % 10 ^ '0'; }
io_out& operator << (int x) {
if(x < 0) x = -x, *s++ = '-';
write(x); return *this;
}
io_out& operator << (char x) { *s++ = x; return *this; }
} out;
struct point { double x, y; } ;
bool cmp(point a, point b) { return a.x < b.x; }
int n;
const int maxn = 1e5 + 51;
point p[maxn];
int st[maxn], v = 0;
double ans = 0;
double dis(int a, int b) { return sqrt((p[a].x - p[b].x) * (p[a].x - p[b].x) + (p[a].y - p[b].y) * (p[a].y - p[b].y)); }
double ChaJi(point x, point y) { return x.x * y.y - x.y * y.x; }
point operator - (point x, point y) { return {x.x - y.x, x.y - y.y};}
double cross(int x, int y, int z) { return ChaJi(p[y] - p[x], p[z] - p[x]); }
void ins(int d) {
while(v >= 2 && cross(st[v - 1], st[v], d) <= 0) --v;
st[++ v] = d;
}
signed main() {
#ifdef LOCAL
freopen("testdata.in", "r", stdin);
#endif
ios :: sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
cin >> n ;
for(int i = 1 ; i <= n ; i ++)
cin >> p[i].x >> p[i].y;
sort(p + 1, p + n + 1, cmp);
st[++ v] = 1, st[++ v] = 2;
for(int i = 3 ; i <= n ; i ++)
ins(i);
for(int i = 2 ; i <= v ; i ++)
ans += dis(st[i - 1], st[i]);
st[v = 1] = n, st[++ v] = n - 1;
for(int i = n - 2 ; i ; i --)
ins(i);
for(int i = 2 ; i <= v ; i ++)
ans += dis(st[i - 1], st[i]);
cout << fixed << setprecision(2) << ans << '
';
return 0;
}