[计算几何]判断线段相交(跨立实验)

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89875253

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思考

看完视频之后,

发现SCY讲得真(mo)好(hu)。

下面我来总结一下规律:
在这里插入图片描述
在这里插入图片描述

我们以 p 1 p_1 为原点,判断 p 3 p_3 p 2 p_2 , p 2 p_2 p 4 p_4 是否是同一个方向旋转(注意是 p 3 p_3 p 2 p_2 p 2 p_2 p 4 p_4 ),可以利用叉乘来理解。

p 3 p_3 为原点的情况同理。

像上图就很好理解。

主要处理下列这种特殊情况。

在这里插入图片描述
这是以 p 1 p_1 为原点, p 2 , p 3 p_2,p_3 共点,它们叉乘之积为0。

我们再来一种普遍情况。
在这里插入图片描述
类似这样的, p 2 , p 3 p_2,p_3 共线,或其它两点或两点以上共线的,我们肯定有一个两两叉乘之积为 0 0 的结果,那么可以判断,现作为原点(即SCY中的标准点),以上图为例,我们可以判断

if(mul(p3,p2,p1)==0&&mymin(p1.x,p2.x)<=p3.x&&mymax(p1.x,p2.x)>=p3.x)return true;

p 3 . x p_3.x 是否在 [ m i n ( p 1 . x , p 2 . x ) , m a x ( p 1 . x , p 2 . x ) ] [min(p_1.x,p_2.x),max(p_1.x,p_2.x)] 这个范围之中,证明它是否有被覆盖。

但是这样还不行。

比如说:

在这里插入图片描述
所以我们还要再判断一下 y y 是否在范围才行。

我们这里可以根据SCY贴在题面上的快速排斥实验来进行判断。

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=1e4+10;
struct node{double x,y;};
struct line{node p1,p2;}a[N];
double mul(node p1,node p2,node p0)
{
    double x1=p1.x-p0.x,x2=p2.x-p0.x;
    double y1=p1.y-p0.y,y2=p2.y-p0.y;
    return x1*y2-x2*y1;
}
double mymin(double x,double y){return x<y?x:y;}
double mymax(double x,double y){return x>y?x:y;}
bool pd(line l1,line l2)
{
    node p1=l1.p1;
    node p2=l1.p2;
    node p3=l2.p1;
    node p4=l2.p2;
    if(mymax(p1.x,p2.x)<mymin(p3.x,p4.x)||mymax(p1.y,p2.y)<mymin(p3.y,p4.y)
		||mymax(p3.x,p4.x)<mymin(p1.x,p2.x)||mymax(p3.y,p4.y)<mymin(p1.y,p2.y))return false;
    if(mul(p3,p2,p1)*mul(p2,p4,p1)>0&&mul(p1,p4,p3)*mul(p4,p2,p3)>0)return true;
    if(mul(p3,p2,p1)==0&&mymin(p1.x,p2.x)<=p3.x&&mymax(p1.x,p2.x)>=p3.x)return true;
    if(mul(p2,p4,p1)==0&&mymin(p1.x,p2.x)<=p4.x&&mymax(p1.x,p2.x)>=p4.x)return true;
    if(mul(p1,p4,p3)==0&&mymin(p3.x,p4.x)<=p1.x&&mymax(p3.x,p4.x)>=p1.x)return true;
    if(mul(p4,p2,p3)==0&&mymin(p3.x,p4.x)<=p2.x&&mymax(p3.x,p4.x)>=p2.x)return true;
    return false;
}
int b[N];
int main()
{
    int n;scanf("%d",&n);int tot=0;
    for(int i=1;i<=n;i++)scanf("%lf%lf%lf%lf",&a[i].p1.x,&a[i].p1.y,&a[i].p2.x,&a[i].p2.y);
    for(int i=1;i<=n;i++)
    {
        bool bk=true;
        for(int j=i+1;j<=n;j++)
            if(pd(a[i],a[j])){bk=false;break;}
        if(bk)b[++tot]=i;
    }
    for(int i=1;i<tot;i++)printf("%d ",b[i]);
    printf("%d\n",b[tot]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89875253