感谢大佬的代码和讲解线段相交

题目 

题目描述

平面直角坐标系中有一条线段 AB 和一条线段 CD ,求线段 CD 和线段 AB 的相交判断。

输入描述

第一行输入一个 T ,代表测试数据量

每组测试数据输入有两行,每行两个实数坐标 (x,y) 分别代表 A,B,C,D 四个点。

输出描述

若 AB 与 CD 规范相交, 输出 2

若 AB 与 CD 不规范相交, 输出 1

若 AB 与 CD 不相交, 输出 0

输入输出样例

示例 1

输入

3
6 2 3 4
4 5 2 2
7 7 10 1
7 7 3 9
1 6 3 5
2 5 1 4

输出

2
1
0

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

 思路

我i们设定两个判定条件:

1.判定两条线段所在的最小矩形是否有重叠的部分:

这条判断标准的原理很简单,如果两条线段所在的最小矩形都没有重叠部分,那么两条线段就不可能相交,我们只需要比较线段的两个端点的x,y值就可以判定

2.通过叉乘判断A,B,C,D四个点的相对位置,这里是叉乘的解释定义

我们发现,当我们在判断c,d是否在ab两端时,如果ca和ab的叉乘与da和ab的叉乘符号相反,就说明c,d在ab的两端。我们判断ab是否在cd两端时也是用同样的思路。只有ab和cd都在对方的两端时,才说明两个线段相交。

规范相交:线段的端点不在另一条线段上

不规范相交:线段的端点在另一条线段上

本题要求我们求规范和不规范相交,我们只需要稍微改一下判定条件

代码1

class point(): #定义类
    def __init__(self,x,y):
        self.x=x
        self.y=y   

def cross(p1,p2,p3):
    #跨立实验,先求向量p1p2和向量p1p3,再求他们的叉乘
    x1=p2.x-p1.x
    y1=p2.y-p1.y
    x2=p3.x-p1.x
    y2=p3.y-p1.y
    return x1*y2-x2*y1     

def IsIntersec(p1,p2,p3,p4): #判断两线段是否相交

    #快速排斥,以l1、l2为对角线的矩形必相交,否则两线段不相交
    if(max(p1.x,p2.x)>=min(p3.x,p4.x)    #矩形1最右端大于矩形2最左端
    and max(p3.x,p4.x)>=min(p1.x,p2.x)   #矩形2最右端大于矩形最左端
    and max(p1.y,p2.y)>=min(p3.y,p4.y)   #矩形1最高端大于矩形最低端
    and max(p3.y,p4.y)>=min(p1.y,p2.y)): #矩形2最高端大于矩形最低端

    #若通过快速排斥则进行跨立实验
        if(cross(p1,p2,p3)*cross(p1,p2,p4)<0
           and cross(p3,p4,p1)*cross(p3,p4,p2)<0):
            D=2
        elif (cross(p1,p2,p3)*cross(p1,p2,p4)==0
           and cross(p3,p4,p1)*cross(p3,p4,p2)==0):
            D=1
        else:
            D=0
    return D

t=int(input())
for i in range(t):
    p1,p2,p3,p4=point(0,0),point(0,0),point(0,0),point(0,0)
    x=list(map(float,input().split()))
    y=list(map(float,input().split()))
    p1.x,p1.y=x[0],x[1]
    p2.x,p2.y=x[2],x[3]
    p3.x,p3.y=y[0],y[1]
    p4.x,p4.y=y[2],y[3]
    print(IsIntersec(p1,p2,p3,p4))

代码2

通过元组输入数据,有些难懂,思路和代码1一样,仅作参考

def Cross(a,b,c):
     return (c[1]-a[1])*(b[0]-a[0])-(c[0]-a[0])*(b[1]-a[1])
    

def intersection(a,b,c,d):
    if max(a[0],b[0])<min(c[0],d[0]) or max(a[1],b[1])<min(c[1],d[1])\
      or min(a[0],b[0])>max(c[0],d[0]) or min(a[1],b[1])>max(c[1],d[1]):
        print(0)
        return
    #print(Cross(a,b,c)*Cross(a,b,d))
    #print(Cross(c,d,a)*Cross(c,d,b))
    if Cross(a,b,c)*Cross(a,b,d)>0 or Cross(c,d,a)*Cross(c,d,b)>0:
        print(0)
        return
    if Cross(a,b,c)*Cross(a,b,d)==0:
        print(1)
        return
    print(2)
    return

t=int(input())
for i in range(t):
    x=list(map(float,input().split()))
    y=list(map(float,input().split()))
    a,b=list((x[0],x[1])),list((x[2],x[3]))
    c,d=list((y[0],y[1])),list((y[2],y[3]))
    intersection(a,b,c,d)