zoukankan      html  css  js  c++  java
  • [hdu4629 Burning]三角形面积并,扫描线

    题意:给n个三角形,分别求覆盖1次~n次的总面积

    思路: 对每个y坐标作一条平行于x轴的直线,按直线从下往上处理,每两条直线之间为若干梯形(也可以是三角形)首尾相连的情况,从左扫到右时,用一个变量cnt记录当前区域被覆盖的次数,遇到入边cnt++,遇到出边cnt--,边扫边更新答案。入边表示这条边的右边在三角形内部,出边表示这条边的右边在三角形的外部。思路并不复杂,只是代码稍长点。

    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define copy(a, b)          memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    //#ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    //#endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    template<typename T>
    void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}
    template<typename T>
    void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}
    
    const double PI = acos(-1.0);
    const int INF = 1e9 + 7;
    const double EPS = 1e-8;
    
    /* -------------------------------------------------------------------------------- */
    
    const int maxn = 57;
    
    int dcmp(double a) {
        if (abs(a) < EPS) return 0;
        return a > 0? 1 : -1;
    }
    
    struct Point {
        double x, y;
        void read() {
            int x, y;
            scanf("%d%d", &x, &y);
            this->x = x;
            this->y = y;
        }
        Point(double x, double y) {
            this->x = x;
            this->y = y;
        }
        Point() {}
        Point operator - (const Point &that) const {
            return Point(this->x - that.x, this->y - that.y);
        }
        bool operator < (const Point &that) const {
            return dcmp(this->y - that.y) < 0 || dcmp(this->y - that.y) == 0 &&
                    dcmp(this->x - that.x) < 0;
        }
        Point operator * (const double &m) const {
            return Point(this->x * m, this->y * m);
        }
    };
    struct Segment {
        Point a, b;
        Segment(Point a, Point b) {
            this->a = a;
            this->b = b;
        }
        Segment() {}
        bool operator < (const Segment &that) const {
            return dcmp(this->a.x + this->b.x - that.a.x - that.b.x) < 0;
        }
    };
    Point point[maxn * maxn * 9];
    Segment seg[maxn * 3];
    int type[maxn * 3];
    double ans[maxn];
    
    double cross(const Point &a, const Point &b) {
        return a.x * b.y - a.y * b.x;
    }
    
    bool onMid(Point a, Point b, Point c) {
        return dcmp(cross(c - a, b - a)) == 0;
    }
    bool onLeft(Point a, Point b, Point c) {
        return dcmp(cross(c - a, b - a)) < 0;
    }
    bool Intersect(Segment A, Segment B) {
        int r1 = dcmp(cross(A.b - A.a, B.a - A.a));
        int r2 = dcmp(cross(A.b - A.a, B.b - A.a));
        int r3 = dcmp(cross(B.b - B.a, A.a - B.a));
        int r4 = dcmp(cross(B.b - B.a, A.b - B.a));
        return (r1 ^ r2) || (r3 ^ r4);
    }
    Point getLineIntersection(Segment A, Segment B) {
        Point u = A.a - B.a, v = A.b - A.a, w = B.b - B.a;
        double t = cross(w, u) / cross(v, w);
        return A.a - v * -t;
    }
    double Area(Segment A, Segment B) {
        return fabs((A.a.x - B.a.x + A.b.x - B.b.x) * (A.a.y - A.b.y) / 2);
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int T, n, cs, cp;
        cin >> T;
        while (T --) {
            cin >> n;
            cp = cs = 0;
            for (int i = 0; i < n; i ++) {
                Point p[3];
                for (int j = 0; j < 3; j ++) p[j].read();
                if (onMid(p[0], p[1], p[2])) continue;
                sort(p, p + 3);
                seg[cs ++] = Segment(p[0], p[1]);
                seg[cs ++] = Segment(p[0], p[2]);
                seg[cs ++] = Segment(p[1], p[2]);
                if (onLeft(p[0], p[2], p[1])) {
                    type[cs - 3] = type[cs - 1] = 1;
                    type[cs - 2] = -1;
                }
                else {
                    type[cs - 3] = type[cs - 1] = -1;
                    type[cs - 2] = 1;
                }
            }
            for (int i = 0; i < cs; i ++) {
                for (int j = i + 1; j < cs; j ++) {
                    if (Intersect(seg[i], seg[j]))
                        point[cp ++] = getLineIntersection(seg[i], seg[j]);
                }
            }
            sort(point, point + cp);
            vector<double> Y;
            for (int i = 0; i < cp; i ++) {
                if (!i || dcmp(point[i].y - point[i - 1].y) != 0) Y.pb(point[i].y);
            }
            fillchar(ans, 0);
            for (int i = 1; i < Y.size(); i ++) {
                vector<pair<Segment, int> > S;
                for (int j = 0; j < cs; j ++) {
                    if (dcmp(seg[j].a.y - Y[i - 1]) <= 0 && dcmp(seg[j].b.y - Y[i]) >= 0) {
                        Point a = seg[j].a, b = seg[j].b;
                        double d = (b.x - a.x) / (b.y - a.y);
                        double x1 = a.x + d * (Y[i - 1] - a.y), x2 = a.x + d * (Y[i] - a.y);
                        S.pb(mp(Segment(Point(x1, Y[i - 1]), Point(x2, Y[i])), type[j]));
                    }
                }
                sort(all(S));
                int cnt = 0;
                for (int j = 0; j < S.size(); j ++) {
                    if (cnt) ans[cnt] += Area(S[j - 1].X, S[j].X);
                    cnt += S[j].Y;
                }
            }
            for (int i = 1; i <= n; i ++) {
                printf("%.10f
    ", ans[i]);
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    Truck History(poj 1789)
    Highways poj 2485
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    115. Distinct Subsequences
    114. Flatten Binary Tree to Linked List
    113. Path Sum II
    109. Convert Sorted List to Binary Search Tree
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/jklongint/p/4724561.html
Copyright © 2011-2022 走看看