凸包 周长 模板

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

struct Point {
    double x, y;
    Point friend operator - (Point a, Point b) {
        return {a.x - b.x, a.y - b.y};
    }
}p[105], Stack[105];

double X(Point a, Point b) {
    return a.x * b.y - a.y * b.x;
}

double multi(Point p1, Point p2, Point p3) {
    return X(p2 - p1, p3 - p1);
}

double dis(Point a, Point b) {
    Point c = a - b;
    return sqrt(c.x * c.x + c.y * c.y);
}
// 极角排序
int cmp(Point a, Point b) {
    double x = X(a - p[1], b - p[1]);
    
    if(x > 0) return 1;
    if(x == 0 && dis(a, p[1]) < dis(b, p[1])) return 1;
    
    return 0;
}

int main()
{
    int N;
    while(scanf("%d", &N) && N)
    {
        for(int i = 1; i <= N; i++)
            scanf("%lf %lf", &p[i].x, &p[i].y);
        // N 等于 1 和 2 特殊判断
        if(N == 1){
            printf("0.00\n");
            continue;
        }
        else if(N == 2){
            printf("%.2f\n", dis(p[1], p[2]));
            continue;
        }
        // 先选出点集中y坐标最小的点,如果y坐标相同则相同点中x坐标最小的点
        int k = 1;
        for(int i = 2; i <= N; i++)
            if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x))
                k = i;
        swap(p[1], p[k]);
        // 按极角排序
        sort(p + 2, p + N + 1, cmp);
        Stack[1] = p[1];
        Stack[2] = p[2];
        int tot = 2;
        for(int i = 3; i <= N; i++) {
            // 发现在栈里边一个顶点处没有向左转时,就把该顶点移除出去
            while(tot >= 2 && multi(Stack[tot - 1], Stack[tot], p[i]) <= 0) tot--;
            Stack[++tot] = p[i];
        }
        // 便于下边计算
        Stack[tot + 1] = Stack[1];
        double sum = 0;
        for(int i = 1; i <= tot; i++) {
            sum += dis(Stack[i], Stack[i + 1]);
        }
        printf("%.2f\n", sum);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/MallowFlower/article/details/81567421
今日推荐