[CQOI2006]凸多边形
一年前写的代码现在已经惨不忍睹了,趁着 olinr讲计算几何,再打一遍板子。
半平面交的步骤是:
-
将所有半平面极角排序
-
维护一个双端队列,按照极角序更新首尾的半平面,然后插入半平面
-
最后再将首尾更新一次
最后队列里所有的半平面即为答案。
下面是重写后的代码,感觉好看多了~
#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
", res / 2);
return 0;
}