zoukankan      html  css  js  c++  java
  • 洛谷 P4196 [CQOI2006]凸多边形 (半平面交)

    题目链接:P4196 [CQOI2006]凸多边形

    题意

    给定 (n) 个凸多边形,求它们相交的面积。

    思路

    半平面交

    半平面交的模板题。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    const db eps = 1e-10;  
    const db pi = acos(-1.0);  
    const ll inf = 0x3f3f3f3f3f3f3f3f;  
    const ll maxn = 1e3 + 10;
    
    inline int dcmp(db x) {
        if(fabs(x) < eps) return 0;
        return x > 0? 1: -1;
    }
    
    class Point {
    public:
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) {}
        inline void input() {
            scanf("%lf%lf", &x, &y);
        }
        bool operator<(const Point &a) const {
            return (!dcmp(x - a.x))? dcmp(y - a.y) < 0: x < a.x;
        }
        bool operator==(const Point &a) const {
            return dcmp(x - a.x) == 0 && dcmp(y - a.y) == 0;
        }
        db dis2(const Point a) {
            return pow(x - a.x, 2) + pow(y - a.y, 2);
        }
        db dis(const Point a) {
            return sqrt(dis2(a));
        }
    
        db dis2() {
            return x * x + y * y;
        }
        db dis() {
            return sqrt(dis2());
        }
        Point operator+(const Point a) {
            return Point(x + a.x, y + a.y);
        }
        Point operator-(const Point a) {
            return Point(x - a.x, y - a.y);
        }
        Point operator*(double p) {
            return Point(x * p, y * p);
        }
        Point operator/(double p) {
            return Point(x / p, y / p);
        }
        db dot(const Point a) {
            return x * a.x + y * a.y;
        }
        db cross(const Point a) {
            return x * a.y - y * a.x;
        }
        db ang(Point a) {
            return acos((a.dis() * dis()) / dot(a));
        }
    };
    typedef Point Vector;
    
    Point p[maxn], ip[maxn];
    
    class Line {
    public:
        Point s, e;
        db angle;
        Line() {}
        Line(Point s, Point e) : s(s), e(e) {}
        inline void input() {
            s.input();e.input();
        }
        bool operator<(const Line &a) const {
            Line l = a;
            if(dcmp(angle - l.angle) == 0) {
                return l.toLeftTest(s) == 1;
            }
            return angle < l.angle;
        }
        void get_angle() {
            angle = atan2(e.y - s.y, e.x - s.x);
        }
        int toLeftTest(Point p) {
            if((e - s).cross(p - s) > 0) return 1;
            else if((e - s).cross(p - s) < 0) return -1;
            return 0;
        }
        int linecrossline(Line l) {
            if(dcmp((e - s).cross(l.e - l.s)) == 0) {
                if(dcmp((l.s - e).cross(l.e - s)) == 0) {
                    return 0;
                }
                return 1;
            }
            return 2;
        }
        Point crosspoint(Line l) {
    		db a1 = (l.e - l.s).cross(s - l.s);
    		db a2 = (l.e - l.s).cross(e - l.s);
            db x = (s.x * a2 - e.x * a1) / (a2 - a1);
            db y = (s.y * a2 - e.y * a1) / (a2 - a1);
            if(dcmp(x) == 0) x = 0;
            if(dcmp(y) == 0) y = 0;
    		return Point(x, y);
    	}
    };
    
    Line l[maxn], q[maxn];
    
    db half_plane(int cnt) {
        sort(l + 1, l + 1 + cnt);
        // for(int i = 1; i <= cnt; ++i) {
        //     cout << l[i].s.x << " " << l[i].s.y << " ";
        //     cout << l[i].e.x << " " << l[i].e.y << endl;
        // }
        int tmp = 1;
        for(int i = 2; i <= cnt; ++i) {
            if(dcmp(l[i].angle - l[tmp].angle) == 1) l[++tmp] = l[i];
        }
        cnt = tmp;
        int head = 1, tail = 2;
        q[1] = l[1], q[2] = l[2];
        for(int i = 3; i <= cnt; ++i) {
            while(head < tail && l[i].toLeftTest(q[tail].crosspoint(q[tail - 1])) == -1) {
                --tail;
            }
            while(head < tail && l[i].toLeftTest(q[head].crosspoint(q[head + 1])) == -1) {
                ++head;
            }
            q[++tail] = l[i];
        }
    
        while(head < tail && q[head].toLeftTest(q[tail].crosspoint(q[tail - 1])) == -1) {
            --tail;
        }
        while(head < tail && q[tail].toLeftTest(q[head].crosspoint(q[head + 1])) == -1) {
            ++head;
        }
    
        if(tail - head + 1 <= 2) {
            return 0.0;
        }
    
        tmp = 0;
        for(int i = head; i < tail; ++i) {
            ip[++tmp] = q[i].crosspoint(q[i + 1]);
        }
        ip[++tmp] = q[head].crosspoint(q[tail]);
        db ans = 0;
        for(int i = 3; i <= tmp; ++i) {
            ans += (ip[i - 1] - ip[1]).cross(ip[i] - ip[1]);
        }
        return ans * 0.5;
    }
    
    int main() {
        int n;
        scanf("%d", &n);
        int cnt = 0;
        for(int i = 1; i <= n; ++i) {
            int m;
            scanf("%d", &m);
            for(int i = 0; i < m; ++i) {
                p[i].input();
                if(i) {
                    l[++cnt].e = p[i];
                    l[cnt].s = p[i - 1];
                    l[cnt].get_angle();
                }
            }
            l[++cnt].e = p[0];
            l[cnt].s = p[m - 1];
            l[cnt].get_angle();
        }
        printf("%.3lf
    ", half_plane(cnt));
        return 0;
    }
    
  • 相关阅读:
    An analysis of a simple Java basic interview question: short s1=1; s1 = s1 +1 will report an error?
    <bits/stdc++.h> in C++
    linux 下配置可视化git 冲突合并工具kdiff3
    加分
    对老师的意见和课程总结
    12月19日
    12月18日
    12月17日
    12月16日
    12月15日
  • 原文地址:https://www.cnblogs.com/wulitaotao/p/11502378.html
Copyright © 2011-2022 走看看