二维凸包模板

[LuoguP2742]

凸包,就是说用一根有弹性的橡皮筋来围住平面上一堆点,然后求这根橡皮筋的长度

这里要有一些前置芝士:向量积

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 }
View Code

 

 

posted @ 2019-12-04 20:06  Sun-dial  阅读(186)  评论(0编辑  收藏  举报