zoukankan      html  css  js  c++  java
  • 51nod--1264 线段相交 (计算几何基础, 二维)

    题目:

    1264 线段相交
    基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注
    给出平面上两条线段的两个端点,判断这两条线段是否相交(有一个公共点或有部分重合认为相交)。 如果相交,输出”Yes”,否则输出”No”。
    Input
    第1行:一个数T,表示输入的测试数量(1 <= T <= 1000)
    第2 - T + 1行:每行8个数,x1,y1,x2,y2,x3,y3,x4,y4。(-10^8 <= xi, yi <= 10^8)
    (直线1的两个端点为x1,y1 | x2, y2,直线2的两个端点为x3,y3 | x4, y4)
    Output
    输出共T行,如果相交输出”Yes”,否则输出”No”。
    Input示例
    2
    1 2 2 1 0 0 2 2
    -1 1 1 1 0 0 1 -1
    Output示例
    Yes
    No

    分析:

    在二维中, 对于两个线段相交, 不包括重叠, 端点可以用向量的叉积来判断, 
    部分重叠, 则说明必有一个点在另一条线段上(不包括端点), 则叉积为0, 点积是 < 0 的;
    对于端点重叠的, 判断一下点是否相等就可以了。
    

    实现:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const double eps = 1e-8;
    int dcmp(double x) {
        return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1);
    }
    
    struct Point {
        double x, y;
        Point(double _x = 0, double _y = 0) :
            x(_x), y(_y) {}
    };
    
    typedef Point Vector;
    
    Vector operator - (Point A, Point B) { return Vector (A.x-B.x, A.y-B.y); }
    bool operator == (Point A, Point B) { return dcmp(A.x-B.x) == 0 && dcmp(A.y-B.y) == 0; }
    double Dot (Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
    double Cross (Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
    bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) { ///不包括端点的两线段相交。
        double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1),
                c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
        return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
    }
    bool PointOnSegment(Point p, Point a1, Point a2) { /// 判断点是否在线段上。
        return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p,a2-p)) < 0;
    }
    
    Point d[4];
    int main()
    {
        int T;
        cin >> T;
        while(T--) {
            for(int i = 0; i < 4; ++i)
                cin >> d[i].x >> d[i].y;
            int cnt = 0;
            cnt += (d[0] == d[2] || d[1] == d[3] || d[0] == d[3] || d[1] == d[2]);
            cnt += (PointOnSegment(d[0],d[2],d[3]) || PointOnSegment(d[1],d[2],d[3]));
            cnt += SegmentProperIntersection(d[0],d[1],d[2],d[3]);
            if(cnt) printf("Yes
    ");
            else printf("No
    ");
        }
    }
    
  • 相关阅读:
    学英语舌尖效应(转)
    winform程序防止重复运行
    label字符自动换行(转自网络)
    C# WINFORM中的combobox.items.add实现像web开发那样,添加显示内容text和实际value值
    三极管开关电路设计(转)
    ASPNET+ArcGIS+Flex初次使用笔记
    转:oracle日期函数集锦
    网站开发人员应该知道的62件事
    cassandra的安装与使用
    datejs一个很好用的时间日期JavaScript组件
  • 原文地址:https://www.cnblogs.com/aoxuets/p/5506847.html
Copyright © 2011-2022 走看看