二维凸包模板
凸包,就是说用一根有弹性的橡皮筋来围住平面上一堆点,然后求这根橡皮筋的长度
这里要有一些前置芝士:向量积
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }