【TOJ 1288】计算几何练习题――线段相交(模板题)

描述

线段相交测试在计算几何中是经常用到的,给定线段P1P2(P1和P2是线段的两端点,且不重合)、P3P4(P3和P4是线段的两端点,且不重合),判断P1P2和P3P4是否相交。P1P2和P3P4不重合,即指只存在一个点P,它既落在P1P2上又落在P3P4上(含线段的端点)。

输入

输入数据有多组,第一行为测试数据的组数N,下面包括2N行,每组测试数据含2行,第一行为P1P2的坐标值,第二行为P3P4的坐标值,比如下面的数据
1
0 0 1 1
2 2 3 3
表示P1、P2、P3、P4的坐标分别为:P1(0,0),P2(1,1),P3(2,2),P4(3,3)

输出

判断每组数据中的线段P1P2和P3P4是否相交,如果相交输出YES,否则输出NO。每组数据输出占一行。

样例输入

1
0 0 1 1
2 2 3 3

样例输出

NO

题解

判断两线段是否相交:

① 快速排斥

就是初步的判断一下,两条线段是不是相交,以两条线段为对角线的矩形,如果不重合的话,那么两条线段一定不可能相交。

1.线段ab的低点低于cd的最高点(可能重合)

2.cd的最左端小于ab的最右端(可能重合)

3.cd的最低点低于ab的最高点(加上条件1,两线段在竖直方向上重合)

4.ab的最左端小于cd的最右端(加上条件2,两直线在水平方向上重合)

综上4个条件,两条线段组成的矩形是重合的。

② 跨立实验

如果两条线段相交,那么必须跨立,就是以一条线段为标准,另一条线段的两端点一定在这条线段的两段

即A、B两点在线段CD的两端,C、D两点在线段AB的两端

这里就用到了向量X乘的知识点,有向量X乘的物理意义知:AB x CD=-CD x AB

看下图:

(CA x CD)·(CB x CD)<=0 则说明向量CA、CB对于向量CD的方向不同,则A、B在线段CD的两侧,由此可以判断其他点

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x,y;
}a,b,c,d;
bool judge(node a,node b,node c,node d)
{
    //快速排斥
    if(!(min(a.x,b.x)<=max(c.x,d.x)&&min(c.x,d.x)<=max(a.x,b.x)&&min(a.y,b.y)<=max(c.y,d.y)&&min(c.y,d.y)<=max(a.y,b.y)))
        return false;

    //跨立实验
    double u,v,w,z;
    u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);  //AC×AB
    v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);  //AD×AB
    w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);  //CA×AB
    z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);  //CB×AB

    if(u*v<=1e-9&&w*z<=1e-9)
        return true;
    return false;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y;
        if(judge(a,b,c,d))
            printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/kannyi/p/9043424.html

时间: 2024-09-28 18:07:25

【TOJ 1288】计算几何练习题――线段相交(模板题)的相关文章

[POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]

可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <vector> using namespace std; int n,q,tot,a[110000]; in

Pick-up sticks(计算几何_线段相交)

Description Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to find the top sticks, that is these sticks such that there is no stick on top of them. Stan has noticed

LA 2191电位计(线段树模板题)

线段树模板题,没啥好说的.....注意输出是case之间空一行就行.........之前一直没注意,一直wa 代码如下: #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #includ

1270. 数列区间最大值(climits用法+线段树模板题)

题目链接: https://www.acwing.com/problem/content/1272/ 题解: 线段树模板题,单点求和.区间查询都可 AC代码: #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <climits> using namespace std; const int N = 1e5+10; int a

P1243~P1247 线段树模板题总结

前言 这几天刚刚刷了5道线段树(水)题,现在来总结一下. 首先是犯的不少错误: 1.建树.更新函数没有return.这是最气的,每次最后程序错误查了半天也没查出来,最后发现是没有return.递归边界要return,递归边界要return,递归边界要return,重要的事情说三遍. 2.判断查找区间于线段的变量写反.听说这个是常犯错误. 然后说一下学线段树的收获.线段树的代码量的确多,很能练自己的思维,而且学的过程中简单的理解了一下#define的用处.线段树用来解决区间查询,区间修改都很方便,

HDU 1166 线段树模板题

坐了3天的火车,终于到外婆家了(┬_┬).这次北京之旅颇有感触,虽然学到的东西不是很多(主要是自己的原因,没有认真学,并不是老师讲的不好),不过出去见见世面也是好的.最后一场比赛印象颇深,被虐的有点惨....记得当时有道题感觉自己能过,想用数组模拟链表水过,可是无论怎么优化一直超时@[email protected]后面比完后听朋友说那题应该用线段树做,顿时恍然大悟,然并卵,线段树的模板早忘了.....今天做道线段树的模板题先复习一下,过会再想想那道题. 敌兵布阵 Time Limit: 200

【计算几何】线段相交

问题描述:已知两条线段P1P2和Q1Q2,判断P1P2和Q1Q2是否相交,若相交,求出交点. 两条线段的位置关系可以分为三类:有重合部分.无重合部分但有交点.无交点. 算法的步骤如下: 1.快速排斥实验. 设以线段P1P2为对角线的矩形为R,设以线段Q1Q2为对角线的矩形为T,如果R和T不相交,则两线段不相交. 2.跨立实验. 如果两线段相交,则两线段必然相互跨立对方. 若P1P2跨立Q1Q2,则矢量(P1-Q1)和(P2-Q1)位于矢量(Q2-Q1)的两侧,即( P1 - Q1 ) × ( Q

[bzoj1568]李超线段树模板题(标志永久化)

题意:要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i. 2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. 解题关键:注意标志的作用 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostrea

POJ 3449 Geometric Shapes --计算几何,线段相交

题意: 给一些多边形或线段,输出与每一个多边形或线段的有哪一些多边形或线段. 解法: 想法不难,直接暴力将所有的图形处理成线段,然后暴力枚举,相交就加入其vector就行了.主要是代码有点麻烦,一步一步来吧. 还有收集了一个线段旋转的函数. Vector Rotate(Point P,Vector A,double rad){ //以P为基准点把向量A旋转rad return Vector(P.x+A.x*cos(rad)-A.y*sin(rad),P.y+A.x*sin(rad)+A.y*co