[CQOI2006]凸多邊形
阿新 • • 發佈:2019-01-04
一年前寫的程式碼現在已經慘不忍睹了,趁著 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\n", res / 2); return 0; }