BZOJ 2618: [Cqoi2006]凸多边形 (半平面交)

模板

CODE

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-10;
const int MAXN = 505;
inline double sqr(double x) { return x*x; }
inline double dcmp(double x) {
    if(x < -eps) return -1;
    if(x > eps) return 1;
    return 0;
}
struct Point {
	double x, y;
	Point(){}
	Point(const double &x, const double &y):x(x), y(y){}
	inline Point operator +(const Point &o)const { return Point(x + o.x, y + o.y); }
	inline Point operator -(const Point &o)const { return Point(x - o.x, y - o.y); }
	inline Point operator *(const double &k)const { return Point(x * k, y * k); }
	inline double operator *(const Point &o)const { return x * o.y - y * o.x; }
	inline friend double dist(const Point &A, const Point &B) { return sqrt(sqr(A.x-B.x) + sqr(A.y-B.y)); }
}a[MAXN];
struct Line {
	Point p, v; double angle;
	Line(){}
	Line(const Point &p, const Point &v):p(p), v(v){
		angle = atan2(v.y, v.x);
	}
	inline friend bool On_Right(const Line &l, const Point &p) {
		return dcmp(l.v * (p - l.p)) <= 0;
	}
	inline bool operator <(const Line &o)const {
	    if(!dcmp(angle-o.angle))
	    	return dcmp(v * (o.p - p)) < 0;  //同角度判一下左右关系,必须是严格的判断,否则sort会出错
	    return angle < o.angle;
    }
	inline friend Point Get_Intersection(const Line &l1, const Line &l2) {
		Point u = l1.p - l2.p;
		double k = (l2.v * u) / (l1.v * l2.v);
		return l1.p + l1.v * k;
	}
}arr[MAXN], q[MAXN]; int head, tail;

inline void Insert(const Line &l) {
	while(tail-head > 1 && On_Right(l, Get_Intersection(q[tail-2], q[tail-1]))) --tail;
	while(tail-head > 1 && On_Right(l, Get_Intersection(q[head], q[head+1]))) ++head;
	q[tail++] = l;
}

int n, m, tot;
int main() {
	scanf("%d", &m);
	while(m--) {
		scanf("%d", &n);
		for(int i = 1; i <= n; ++i) {
			scanf("%lf%lf", &a[i].x, &a[i].y);
			if(i > 1) arr[++tot] = Line(a[i-1], a[i]-a[i-1]);
		}
		arr[++tot] = Line(a[n], a[1]-a[n]);
	}

	sort(arr + 1, arr + tot + 1);
	q[tail++] = arr[1];
	for(int i = 2; i <= tot; ++i)
        if(dcmp(arr[i].angle-arr[i-1].angle))
            Insert(arr[i]);
	while(tail-head > 1 && On_Right(q[head], Get_Intersection(q[tail-2], q[tail-1]))) --tail;
	if(tail - head < 3) return puts("0.000"), 0;
	
	Point S = Get_Intersection(q[head], q[tail-1]), last = S;
	double ans = 0;
	for(int i = head+1; i < tail; ++i) {
		Point now = Get_Intersection(q[i], q[i-1]);
		ans += last * now; last = now;
	}
	ans += last * S;
	printf("%.3f
", ans/2);
}

原文地址:https://www.cnblogs.com/Orz-IE/p/12039305.html