凸包,就是说用一根有弹性的橡皮筋来围住平面上一堆点,然后求这根橡皮筋的长度
这里要有一些前置芝士:向量积
Code:

1 #include <bits/stdc++.h>
2 using namespace std;
3 const int N = 1e4 + 7;
4 int n;
5 double ans;
6 struct node{
7 double x, y;
8 }stk[N], a[N];
9 double Cj(node a1, node a2, node b1, node b2) {
10 return (a2.x - a1.x) * (b2.y - b1.y) - (b2.x - b1.x) * (a2.y - a1.y);
11 }//向量的叉积,公式是(x1*y2 - x2 * y1)
12 //如果叉积大于0,代表左旋,反之就是右旋
13 double getdis(node a, node b) {//两点间距离公式
14 return sqrt((double)(a.x - b.x) * (a.x - b.x) + (double)(a.y - b.y) * (a.y - b.y));
15 }
16 bool cmp(node a1, node b) {//按叉积排序
17 double now = Cj(a[1], a1, a[1], b);
18 if (now > 0) return true;
19 if (now == 0) return getdis(a[0], a1) < getdis(a[0], b);
20 //如果共线,就看谁的距离远,因为距离远的包含的范围更大
21 return false;
22 }
23 int main () {
24 scanf("%d", &n);
25 for (int i = 1; i <= n; i++) {
26 scanf("%lf%lf", &a[i].x, &a[i].y);
27 if (i != 1 && a[i].y < a[1].y) {
28 swap(a[1].x, a[i].x);
29 swap(a[1].y, a[i].y);
30 //找到最下方的点作为起点(这个点一定在凸包上)
31 }
32 }
33 sort(a + 2, a + 1 + n, cmp);
34 stk[1] = a[1];
35 int tot = 1;//栈中此时已经有第一个点了
36 for (int i = 2; i <= n; i++) {
37 while (tot > 1 && Cj(stk[tot - 1], stk[tot], stk[tot], a[i]) <= 0) {
38 tot--;
39 //当栈中点数大于1时,且此时此点是右旋方向,就不断出栈,直到为左旋为止
40 }
41 stk[++tot] = a[i];//将该点入栈
42 }
43 stk[tot + 1] = a[1];//因为最后一个点和第一个点之间还有一条边,所以就再加一个
44 for (int i = 1; i <= tot; i++) {
45 ans += getdis(stk[i], stk[i + 1]);
46 }
47 printf("%.2f\n", ans);
48 return 0;
49 }
