[CQOI2006]凸多边形

一年前写的代码现在已经惨不忍睹了,趁着 olinr讲计算几何,再打一遍板子。

半平面交的步骤是:

  1. 将所有半平面极角排序

  2. 维护一个双端队列,按照极角序更新首尾的半平面,然后插入半平面

  3. 最后再将首尾更新一次

最后队列里所有的半平面即为答案。

下面是重写后的代码,感觉好看多了~

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

const double eps  = 1e-6;

struct Vector
{
    double x, y;
    Vector(double x = 0, double y = 0) : x(x), y(y) {}
    double mod() {return sqrt(x * x + y * y);}
};

struct Line
{
    Vector p, v;
}a[510];

int n, nn;

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

bool polar_cmp(const Line &a, const Line &b)
{
    if (fabs(atan2(a.v.y, a.v.x) - atan2(b.v.y, b.v.x)) > eps)
        return atan2(a.v.y, a.v.x) < atan2(b.v.y, b.v.x);
    return (a.v ^ (b.p - a.p)) < 0;
}

Vector inter(const Line &a, const Line &b)
{
    return b.p + b.v * (((b.p - a.p) ^ a.v) / (a.v ^ b.v));
}

void input_poly()
{
    int m, x[55], y[55];
    scanf("%d", &m);
    for (int i = 1; i <= m; i++)
        scanf("%d%d", &x[i], &y[i]);
    x[m + 1] = x[1], y[m + 1] = y[1];
    for (int i = 1; i <= m; i++)
        a[++nn].p = Vector(x[i], y[i]), a[nn].v = Vector(x[i + 1] - x[i], y[i + 1] - y[i]);
}

Line q[2333];
Vector li[2333];
int top, bottom;

bool valid(const Vector p, const Line &l)
{
    return (l.v ^ (p - l.p)) > 0;
}

void insert(const Line &l)
{
    while (top - bottom >= 2 && valid(inter(q[top], q[top - 1]), l) == false)
        top--;
    while (top - bottom >= 2 && valid(inter(q[bottom + 1], q[bottom + 2]), l) == false)
        bottom++;
    q[++top] = l;
}

int main()
{
    int fuck;
    scanf("%d", &fuck);
    for (int i = 1; i <= fuck; i++)
        input_poly();
    sort(a + 1, a + 1 + nn, polar_cmp);
    for (int i = 1; i <= nn; i++)
        if (i == 1 || fabs(atan2(a[i].v.y, a[i].v.x) - atan2(a[i - 1].v.y, a[i - 1].v.x)) > eps)
            a[++n] = a[i];
    for (int i = 1; i <= n; i++)
        insert(a[i]);
    while (top - bottom >= 2 && valid(inter(q[top], q[top - 1]), q[bottom + 1]) == false)
        top--;
    while (top - bottom >= 2 && valid(inter(q[bottom + 1], q[bottom + 2]), q[top]) == false)
        bottom++;
    q[bottom] = q[top];
    for (int i = bottom; i < top; i++)
        li[i] = inter(q[i], q[i + 1]);
    li[top] = li[bottom];
    double res = 0;
    for (int i = bottom; i < top; i++)
        res += (li[i] ^ li[i + 1]);
    printf("%.3f\n", res / 2);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/oier/p/10217818.html