Andrew板子(二维凸包)

题意:

告诉你n个点,求这些点的凸包边长,或者在凸包边上点的数量。

#include <bits/stdc++.h>
using namespace std;

#define ll long long
//#define int ll

const int maxn = 1e5 + 10;
const int N = 4e6 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-7;

inline int rd(){
    int res = 0;char ch = getchar();
    while(!isdigit(ch)){if(ch == '-')  ch = getchar();}
    while(isdigit(ch)){res = res * 10 + (ch - '0'); ch = getchar();}
    return res;
}

inline int sgn(double x){
    if(fabs(x) <= eps)return 0;
    return x < 0 ? -1 : 1;
}

struct Node{
    double x, y;
    Node(){}
    Node(double x, double y):x(x), y(y){}
    Node operator - (Node tmp){return Node(x - tmp.x, y - tmp.y);}
    Node operator + (Node tmp){return Node(x + tmp.x, y + tmp.y);}
    bool operator == (Node tmp) {return !sgn(x - tmp.x) && !sgn(y - tmp.y);}
    bool operator < (Node tmp){
        if(sgn(x - tmp.x) != 0){
            return x < tmp.x;
        }else{
            return y < tmp.y;
        }
    }
};

int n, save;

// 计算叉积,小于0表示b向量在a向量的右方
double cross(Node a, Node b){
    return a.x * b.y - a.y * b.x;
}

double getDis(Node a, Node b){
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

/**
 * @param node 点集
 * @param n 点集数量
 * @param res 在凸包上的点集
 * @return 返回凸包上点的数量
 */
int Andrew(Node *node, int n, Node *res){
    sort(node, node + n);
    n = unique(node, node + n) - node;// 去重
    int cnt = 0;
    for(int i = 0; i < n; i++){
        while(cnt > 1 && sgn(cross(res[cnt - 1] - res[cnt - 2], node[i] - res[cnt - 2])) <= 0)
            cnt--;
        res[cnt++] = node[i];
    }
    int j = cnt;
    for(int i = n - 2; i >= 0; i--){
        while(cnt > j && sgn(cross(res[cnt - 1] - res[cnt - 2], node[i] - res[cnt - 2])) <= 0)
            cnt--;
        res[cnt++] = node[i];
    }
    if(n > 1)cnt--;
    return cnt;
}

Node node[maxn], res[maxn];
int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
        scanf("%lf %lf", &node[i].x, &node[i].y);
    }
    int nodes = Andrew(node, n, res);
    double ans = 0;
    if(nodes == 1)printf("0\n");
    else if(nodes == 2)printf("%.2f\n", getDis(res[0], res[1]));
    else{
        for(int i = 0; i < nodes; i++){
            ans += getDis(res[i], res[(i + 1) % nodes]);
        }
        printf("%.2f\n", ans);
    }
    return 0;
}

 

posted @ 2021-07-21 15:43  塔塔开  阅读(83)  评论(0)    收藏  举报