• Rectangles 【UVA


      题意:有N个矩阵,每个矩阵有两个对角线,现在从每个矩阵的两条对角线中选出一条,使得选出的这N条对角线相互之间没有相交。

      思路:首先我们可以假设,选对角线1或对角线2,那么就能有选1不能选1'这样的情况出现,我们将这样的情况去建图,那么其实就是一个2-SAT问题,那么剩下的就是判断线段交了,这里推荐快速排斥试验+跨立实验。

    计算几何——判断两线段相交

      注意,平行且重叠也算是相交,不能用交点来直接判断。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <bitset>
    #include <unordered_map>
    #include <unordered_set>
    #define lowbit(x) ( x&(-x) )
    #define e 2.718281828459045
    #define INF 0x3f3f3f3f
    #define HalF (l + r)>>1
    #define lsn rt<<1
    #define rsn rt<<1|1
    #define Lson lsn, l, mid
    #define Rson rsn, mid+1, r
    #define QL Lson, ql, qr
    #define QR Rson, ql, qr
    #define myself rt, l, r
    #define pii pair<int, int>
    #define MP(a, b) make_pair(a, b)
    using namespace std;
    typedef unsigned long long ull;
    typedef unsigned int uit;
    typedef long long ll;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    int cmp(double x)
    {
        if(fabs(x) < eps) return 0;
        if(x > 0) return 1;
        else return -1;
    }
    inline double sqr(double x) { return x * x; }
    struct Point
    {
        double x, y;
        Point(double a = 0., double b = 0.):x(a), y(b) {}
        void Input() { scanf("%lf%lf", &x, &y); }
        friend Point operator + (const Point &a, const Point &b)
        { return Point(a.x + b.x, a.y + b.y); }
        friend Point operator - (const Point &a, const Point &b)
        { return Point(a.x - b.x, a.y - b.y); }
        friend bool operator == (const Point &a, const Point &b)
        { return cmp(a.x - b.x) == 0 && cmp(a.y - b.y) == 0; }
        friend Point operator * (const Point &a, const double &b)
        { return Point(a.x * b, a.y * b); }
        friend Point operator / (const Point &a, const double &b)
        { return Point(a.x / b, a.y / b); }
        double norm()
        { return sqrt(sqr(x) + sqr(y)); }
    };
    double det(const Point &a, const Point &b)  //向量叉积
    { return a.x * b.y - a.y * b.x; }
    double dot(const Point &a, const Point &b)  //向量点积
    { return a.x * b.x + a.y * b.y; }
    double dist(const Point &a, const Point &b) //两点距离
    { return (a - b).norm(); }
    Point Rotate_Point(const Point &p, double A)    //op绕原点逆时针旋转A(弧度)
    {
        double tx = p.x, ty = p.y;
        return Point(tx * cos(A) - ty * sin(A), tx * sin(A) + ty * cos(A));
    }
    struct Line
    {
        Point a, b;
        Line(Point x = Point(), Point y = Point()):a(x), b(y) {}
    };
    Line Point_make_line(const Point a, const Point b)
    { return Line(a, b); }
    double dis_Point_Segement(const Point p, const Point s, const Point t)  //p到线段st的距离
    {
        if(cmp(dot(p - s, t - s)) < 0) return (p - s).norm();
        if(cmp(dot(p - t, s - t)) < 0) return (p - t).norm();
        return fabs(det(s - p, t - p) / dist(s, t));
    }
    bool PointOnSegement(Point p, Point s, Point t) //p点是否在线段st上(包括端点)
    { return cmp(det(p - s, t - s)) == 0 && cmp(dot(p - s, p - t)) <= 0; }
    bool parallel(Line a, Line b)   //线段平行
    { return !cmp(det(a.a - a.b, b.a - b.b)); }
    bool line_make_point(Line a, Line b, Point &res)    //线段相交
    {
        if(parallel(a, b)) return false;
        double s1 = det(a.a - b.a, b.b - b.a);
        double s2 = det(a.b - b.a, b.b - b.a);
        res = (a.b * s1 - a.a * s2) / (s1 - s2);
        return true;
    }
    const int maxN = 2e3 + 7;
    int N, n;
    Point a[4];
    bool cmp_P(Point e1, Point e2) { return e1.x == e2.x ? e1.y < e2.y : e1.x < e2.x; }
    Line xl[maxN];
    int head[maxN], cnt;
    struct Eddge
    {
        int nex, to;
        Eddge(int a=-1, int b=0):nex(a), to(b) {}
    } edge[maxN * maxN];
    inline void addEddge(int u, int v)
    {
        edge[cnt] = Eddge(head[u], v);
        head[u] = cnt ++;
    }
    int dfn[maxN], low[maxN], tot, Stap[maxN], Stop, Belong[maxN], Bcnt;
    bool instack[maxN];
    void Tarjan(int u)
    {
        dfn[u] = low[u] = ++ tot;
        Stap[++Stop] = u;
        instack[u] = true;
        for(int i = head[u], v; ~i; i = edge[i].nex)
        {
            v = edge[i].to;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else if(instack[v]) low[u] = min(low[u], dfn[v]);
        }
        if(dfn[u] == low[u])
        {
            int v;
            Bcnt ++;
            do
            {
                v = Stap[Stop --];
                instack[v] = false;
                Belong[v] = Bcnt;
            } while(u ^ v);
        }
    }
    inline void init()
    {
        cnt = 0; tot = Stop = Bcnt = 0;
        for(int i = 0; i <= n; i ++)
        {
            dfn[i] = 0;
            instack[i] = false;
            head[i] = -1;
        }
    }
    double direction(Point p1, Point p2, Point p)
    {
        return (p1.x - p.x) * (p2.y - p.y) - ( p2.x - p.x) * (p1.y - p.y);
    }
    int on_segment(Point p1, Point p2 , Point p )
    {
        double max=p1.x > p2.x ? p1.x : p2.x;
        double min =p1.x < p2.x ? p1.x : p2.x;
        if( p.x >=min && p.x <=max ) return 1;
        else return 0;
    }
    int segments_intersert(Point p1, Point p2, Point p3, Point p4 )
    {
        double d1,d2,d3,d4;
        d1 = direction ( p1, p2, p3 );
        d2 = direction ( p1, p2, p4 );
        d3 = direction ( p3, p4, p1 );
        d4 = direction ( p3, p4, p2 );
        if( d1 * d2 < 0 && d3 * d4 < 0 ) return 1;
        else if( d1 == 0 && on_segment( p1, p2, p3 ) ) return 1;
        else if( d2==0 && on_segment( p1, p2, p4 ) ) return 1;
        else if( d3==0 && on_segment( p3, p4, p1 ) ) return 1;
        else if( d4==0 && on_segment( p3, p4, p2 ) ) return 1;
        return 0;
    }
    int segments_intersert(Line p, Line q) { return segments_intersert(p.a, p.b, q.a, q.b); }
    int main()
    {
        while(scanf("%d", &N) && N)
        {
            n = 0;
            for(int i = 1; i <= N; i ++)
            {
                for(int j = 0; j < 4; j ++) a[j].Input();
                sort(a, a + 4, cmp_P);
                xl[n ++] = Line(a[0], a[3]);
                xl[n ++] = Line(a[1], a[2]);
            }
            init();
            for(int i = 0; i < n; i ++)
            {
                for(int j = (i & 1 ? i + 1 : i + 2); j < n; j ++)
                {
                    if(segments_intersert(xl[i], xl[j]))
                    {
                        addEddge(i, j ^ 1);
                        addEddge(j, i ^ 1);
                    }
                }
            }
            for(int i = 0; i < n; i ++) if(!dfn[i]) Tarjan(i);
            bool ok = true;
            for(int i = 0; ok && i < n; i += 2)
            {
                if(Belong[i] == Belong[i | 1]) ok = false;
            }
            printf(ok ? "YES
    " : "NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    c# 对文件操作
    c# 获取当前绝对路径
    c# 过滤特殊字符
    c# txt代码转换成HTML格式
    c# 对象集合转Json
    c# DataReader转换为Json
    c# DataSet转换为Json
    ABAP-SAP的LUW和DB的LUW的区别
    ABAP-关于隐式与显式的DB Commit
    ABAP-Keyword Documentation
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/14154904.html
Copyright © 2020-2023  润新知