[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\n", ++ cas, area > 0? "Yes" : "No");
    }
    return 0;
}
时间: 2024-11-07 08:53:22

[UVA Live 12931 Common Area]扫描线的相关文章

uva 10405 Longest Common Subsequence (最长公共子序列)

uva 10405 Longest Common Subsequence Sequence 1: Sequence 2: Given two sequences of characters, print the length of the longest common subsequence of both sequences. For example, the longest common subsequence of the following two sequences: abcdgh a

UVA 10405 Longest Common Subsequence

最长公共子系列,简单的dp,不过注意有空格,所以,在读字符串的时候,尽量用gets读,这样基本没问题 #include<iostream> #include<cstdio> #include<string> #include<cstring> using namespace std; int dp[1001][1001]; int MAX(int x,int y) { if (x>y) return x; else return y; } int ma

UVA 10522 - Height to Area(计算几何)

这题就海伦公式带进去就可以了.. 要注意的是,这题的样例,是输入n次错误的输入才停止..,输入的可能是负数. 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const double eps = 1e-8; int t; double Ha, Hb, Hc; int dcmp(double x) { if (

uva 10405 Longest Common Subsequence(最长公共子序列)

经典的最长公共子序列问题,我刚开始用string敲的,就是为了练练手,没想到竟然wa了,还以为我用错了呢...换了字符数还是wa...真无语,这么简单的题快把我弄糊涂了,后来听人说是输入可能有空格...这是巨坑啊,题上都没说清楚,白白wa了几发...就是设一个数组d[i][j]遍历两个字符数组当a[i]==b[j]的时候d[i][j]=d[i-1][j-1]+1.不相等的时候就是d[i][j]=max(d[i-1][j],d[i][j-1]).别忘了初始化.真坑 代码: #include<ios

UVA 10522 Height to Area(知三角形三高求面积)

思路:海伦公式, AC代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n; 6 scanf("%d",&n); 7 double ha, hb, hc, a, b, c; 8 while(~scanf("%lf %lf %lf",&ha,&hb,&hc)) 9 { 10 a = 2.0 / ha; 11 b = 2.0

hdu---(Tell me the area)(几何/三角形面积以及圆面积的一些知识)

Tell me the area Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1876    Accepted Submission(s): 567 Problem Description There are two circles in the plane (shown in the below picture), there is

HDU 1798 Tell me the area (计算几何)

Tell me the area Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1801    Accepted Submission(s): 542 Problem Description There are two circles in the plane (shown in the below picture), there is

Soj题目分类

-----------------------------最优化问题------------------------------------- ----------------------常规动态规划  SOJ1162 I-Keyboard  SOJ1685 Chopsticks SOJ1679 Gangsters SOJ2096 Maximum Submatrix  SOJ2111 littleken bg SOJ2142 Cow Exhibition  SOJ2505 The County

HDU 3622 Bomb Game(二分+2-SAT)

Bomb Game Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5396    Accepted Submission(s): 1925 Problem Description Robbie is playing an interesting computer game. The game field is an unbounde