zoukankan      html  css  js  c++  java
  • [UVA Live 12931 Common Area]扫描线

    题意:判断两个多边形是否有面积大于0的公共部分

    思路:扫描线基础。

    #pragma comment(linker, "/STACK:10240000")
    #include <bits/stdc++.h>
    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))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    
    namespace Debug {
    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;}
    }
    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);}
    /* -------------------------------------------------------------------------------- */
    
    
    const double eps = 1e-10;/** 设置比较精度 **/
    struct Real {
        double x;
        double get() { return x; }
        Real(const double &x) { this->x = x; }
        Real() {}
    
        Real operator + (const Real &that) const { return Real(x + that.x);}
        Real operator - (const Real &that) const { return Real(x - that.x);}
        Real operator * (const Real &that) const { return Real(x * that.x);}
        Real operator / (const Real &that) const { return Real(x / that.x);}
    
        Real operator += (const Real &that) { return Real(x += that.x); }
        Real operator -= (const Real &that) { return Real(x -= that.x); }
        Real operator *= (const Real &that) { return Real(x *= that.x); }
        Real operator /= (const Real &that) { return Real(x /= that.x); }
    
        bool operator < (const Real &that) const { return x - that.x <= -eps; }
        bool operator > (const Real &that) const { return x - that.x >= eps; }
        bool operator == (const Real &that) const { return x - that.x > -eps && x - that.x < eps; }
        bool operator <= (const Real &that) const { return x - that.x < eps; }
        bool operator >= (const Real &that) const { return x - that.x > -eps; }
    };
    
    struct Point {
        Real x, y;
        int read() { return scanf("%lf%lf", &x.x, &y.x); }
        Point(const Real &x, const Real &y) { this->x = x; this->y = y; }
        Point() {}
        Point operator + (const Point &that) const { return Point(this->x + that.x, this->y + that.y); }
        Point operator - (const Point &that) const { return Point(this->x - that.x, this->y - that.y); }
        Real operator * (const Point &that) const { return x * that.x + y * that.y; }
        Point operator * (const Real &that) const { return Point(x * that, y * that); }
        Point operator += (const Point &that)  { return Point(this->x += that.x, this->y += that.y); }
        Point operator -= (const Point &that)  { return Point(this->x -= that.x, this->y -= that.y); }
        Point operator *= (const Real &that)  { return Point(x *= that, y *= that); }
        Real cross(const Point &that) const { return x * that.y - y * that.x; }
    };
    typedef Point Vector;
    
    struct Segment {
        Point a, b;
        Segment(const Point &a, const Point &b) { this->a = a; this->b = b; }
        Segment() {}
        bool intersect(const Segment &that) const {
            Point c = that.a, d = that.b;
            Vector ab = b - a, cd = d - c, ac = c - a, ad = d - a, ca = a - c, cb = b - c;
            return ab.cross(ac) * ab.cross(ad) < 0 && cd.cross(ca) * cd.cross(cb) < 0;
        }
        Point getLineIntersection(const Segment &that) const {
            Vector u = a - that.a, v = b - a, w = that.b - that.a;
            Real t = w.cross(u) / v.cross(w);
            return a + v * t;
        }
    };
    
    Point p1[123], p2[123];
    Segment side1[123], side2[123];
    
    bool cmp(const pair<Segment, int> &a, const pair<Segment, int> &b) {
        return a.X.a.x + a.X.b.x < b.X.a.x + b.X.b.x;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n, m, cas = 0;
        while (cin >> n) {
            for (int i = 0; i < n; i ++) {
                p1[i].read();
                if (i) side1[i - 1] = Segment(p1[i - 1], p1[i]);
            }
            side1[n - 1] = Segment(p1[n - 1], p1[0]);
            cin >> m;
            for (int i = 0; i < m; i ++) {
                p2[i].read();
                if (i) side2[i - 1] = Segment(p2[i - 1], p2[i]);
            }
            side2[m - 1] = Segment(p2[m - 1], p2[0]);
            /** 得到所有的扫描线并排序去重 **/
            vector<Real> Y;
            for (int i = 0; i < n; i ++) Y.pb(p1[i].y);
            for (int i = 0; i < m; i ++) Y.pb(p2[i].y);
            for (int i = 0; i < n; i ++) {
                for (int j = 0; j < m; j ++) {
                    if (side1[i].intersect(side2[j])) {
                        Y.pb(side1[i].getLineIntersection(side2[j]).y);
                    }
                }
            }
            sort(all(Y));
            Y.resize(unique(all(Y)) - Y.begin());
            //Debug::print("Y.size=", Y.size());
            Real area = 0;
            for (int i = 1; i < Y.size(); i ++) {
                vector<pair<Segment, int> > V;
                /** 得到扫描线之间的所有线段 **/
                for (int j = 0; j < n; j ++) {
                    Real miny = side1[j].a.y, maxy = side1[j].b.y;
                    if (miny > maxy) swap(miny, maxy);
                    if (miny <= Y[i - 1] && maxy >= Y[i]) {
                        Point dot1 = side1[j].getLineIntersection(Segment(Point(0, Y[i - 1]), Point(1, Y[i - 1])));
                        Point dot2 = side1[j].getLineIntersection(Segment(Point(0, Y[i]), Point(1, Y[i])));
                        V.pb(mp(Segment(dot1, dot2), 0));
                    }
                }
                for (int j = 0; j < m; j ++) {
                    Real miny = side2[j].a.y, maxy = side2[j].b.y;
                    if (miny > maxy) swap(miny, maxy);
                    if (miny <= Y[i - 1] && maxy >= Y[i]) {
                        Point dot1 = side2[j].getLineIntersection(Segment(Point(0, Y[i - 1]), Point(1, Y[i - 1])));
                        Point dot2 = side2[j].getLineIntersection(Segment(Point(0, Y[i]), Point(1, Y[i])));
                        V.pb(mp(Segment(dot1, dot2), 1));
                    }
                }
                sort(all(V), cmp);
                //Debug::print("V.size=", V.size());
                /** 从左至右统计 **/
                bool in1 = 0, in2 = 0;/** 当前延伸的区域是否在多边形内部 **/
                for (int i = 0; i < V.size(); i ++) {
                    if (in1 && in2) area += V[i].X.a.x - V[i - 1].X.a.x + V[i].X.b.x - V[i - 1].X.b.x;
                    if (V[i].Y) in2 ^= 1;
                    else in1 ^= 1;
                }
            }
            printf("Case %d: %s
    ", ++ cas, area > 0? "Yes" : "No");
        }
        return 0;
    }
    
  • 相关阅读:
    vuejs 踩坑及经验总结
    Factory Method
    【Java】macOS下编译JDK8
    康威定律(Conway's law)
    first-child和first-of-type
    JavaScript 核心学习——继承
    All Tips
    21分钟教会你分析MaxCompute账单
    CTO职场解惑指南系列(一)
    威胁预警|首现新型RDPMiner挖矿蠕虫 受害主机易被添加恶意账户
  • 原文地址:https://www.cnblogs.com/jklongint/p/4803859.html
Copyright © 2011-2022 走看看