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;
    }
    
  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/jklongint/p/4803859.html
Copyright © 2011-2022 走看看