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;
}
原文地址:https://www.cnblogs.com/WuliWuliiii/p/14154904.html