计算几何

二维凸包

#include <cmath>
#include <cstdio>
#include <algorithm>

const int N = 1e5 + 5;

struct Node {
    double x, y;
}a[N], stk[N];

int n, tp, k;
double ans;

bool operator < (const Node &a, const Node &b) {
    return a.x != b.x ? a.x < b.x : a.y < b.y;
}

double Cross(Node a, Node b, Node c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}

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

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%lf%lf", &a[i].x, &a[i].y);
    std::sort(a + 1, a + n + 1);
    stk[k = ++tp] = a[1];
    for (int i = 2; i <= n; ++i) {
        while (tp > k && Cross(stk[tp-1], stk[tp], a[i]) <= 0) tp--;
        stk[++tp] = a[i];
    }
    k = tp;
    for (int i = n - 1; i >= 1; --i) {
        while (tp > k && Cross(stk[tp-1], stk[tp], a[i]) <= 0) tp--;
        stk[++tp] = a[i];
    }
    for (int i = 1; i < tp; ++i)
        ans += Dis(stk[i], stk[i+1]);
    printf("%.2lf
", ans);
    return 0;
}

半平面交

#include <cmath>
#include <cstdio>
#include <algorithm>

const int N = 505;
const double eps = 1e-14;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

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

struct Node {
    double x, y;
}p[N];

Node operator + (const Node &a, const Node &b) { return (Node) {a.x + b.x, a.y + b.y}; }
Node operator - (const Node &a, const Node &b) { return (Node) {a.x - b.x, a.y - b.y}; }
double operator * (const Node &a, const Node &b) { return a.x * b.y - a.y * b.x; }

struct Line {
    Node s, t; double k;
    Line() {}
    Line(Node a, Node b) {
        s = a, t = b; a = b - a; k = atan2(a.y, a.x);
    }
}a[N];

bool operator < (const Line &a, const Line &b) {
    return Dbcmp(a.k - b.k) ? a.k < b.k : Dbcmp((a.t - a.s) * (b.s - a.s)) < 0;
}

int n, m, q[N];
double ans;

Node Get(const Line &a, const Line &b) {
    double k = ((b.s - a.s) * (a.t - a.s)) / ((a.t - a.s) * (b.t - b.s));
    Node ans = b.t - b.s; ans.x *= k; ans.y *= k;
    return b.s + ans;
}

bool Right(const Line &a, const Node &b) {
    return Dbcmp((a.t - a.s) * (b - a.s)) < 0;
}

int main() {
    m = read();
    for (int i = 1; i <= m; ++i) {
        int mi = read();
        p[1] = (Node) {read(), read()};
        for (int j = 2; j <= mi; ++j)
            p[j] = (Node) {read(), read()}, a[++n] = (Line) {p[j-1], p[j]};
        a[++n] = (Line) {p[mi], p[1]};
    }
    std::sort(a + 1, a + n + 1);
    int l = 1, r = 0; m = n; n = 0;
    for (int i = 1; i <= m; ++i)
        if (Dbcmp(a[i].k - a[i-1].k)) a[++n] = a[i];
    for (int i = 1; i <= n; ++i) {
        while (l < r && Right(a[i], Get(a[q[r]], a[q[r-1]]))) r--;
        while (l < r && Right(a[i], Get(a[q[l]], a[q[l+1]]))) l++;
        q[++r] = i;
    }
    while (l < r && Right(a[q[l]], Get(a[q[r]], a[q[r-1]]))) r--;
    for (int i = l; i < r; ++i) p[i] = Get(a[q[i]], a[q[i+1]]);
    p[r] = Get(a[q[r]], a[q[l]]); p[r+1] = p[l];
    for (int i = l; i <= r; ++i) ans += p[i] * p[i+1];
    printf("%.3lf
", ans / 2);
    return 0;
}
原文地址:https://www.cnblogs.com/shawk/p/14259366.html