首页 > 其他分享 >线段相交Ⅲ

线段相交Ⅲ

时间:2023-08-12 19:22:26浏览次数:44  
标签:线段 相交 a1 a2 b1 b2

描述

 

线段相交有两种情形:一种是“规范相交”,另一种是“非规范相交”。规范相交是指两条线段恰有唯一一个不是端点的公共点。即如果一条线段的端点在另一条线段上则不视为相交。如果两条线段有部分重合,也不视为相交。而非规范相交则把以上两种情况都视为相交。如下图所示:

规范相交认为a,b两种情况都是不相交的,而非规范相交认为a,b两种情况都是相交的。

本题要求判断两条线段是否相交。如果是规范相交则输出YES,并输出交点坐标,如果是非规范相交则只需输出YES,如果不相交则输出NO。

 

输入

输入有多组数据,T表示输入数据的组数。每组测试数据有两行第一行输入一条线段的两个端点的坐标,第二行输入另一个线段的两个端点的坐标。

输出

对于每组测试数据,输出一行。如果是规范相交则输出YES,并输出交点坐标(小数点后面保留3位),如果是非规范相交则只需输出YES,如果不相交则输出NO。

样例输入

4
0 0 1 1
0 1 1 0
0 0 2 2
2 2 3 3
0 0 2 2
1.5 1.5 3 3
0 0 1 1
2 2 3 3

样例输出

YES (0.500,0.500)
YES
YES
NO

 

分类讨论,考虑斜率存不存在和共线平行的情况,一般情况直接算出交点,判断是否在两个线段内

#include <bits/stdc++.h>
using namespace std;
struct d
{
    double x,y;
};
int judge(d t,d a1,d a2,d b1,d b2)//2为规范相交,1为非规范相交,0为不相交
{
    if(t.x>min(b1.x,b2.x)&&t.x<max(b1.x,b2.x)&&t.y>min(b1.y,b2.y)&&t.y<max(b1.y,b2.y)&&t.x>min(a1.x,a2.x)&&t.x<max(a1.x,a2.x)&&t.y>min(a1.y,a2.y)&&t.y<max(a1.y,a2.y))//规范相交
    {
        return 2;
    }
    else if(t.x>=min(b1.x,b2.x)&&t.x<=max(b1.x,b2.x)&&t.y>=min(b1.y,b2.y)&&t.y<=max(b1.y,b2.y)&&t.x>=min(a1.x,a2.x)&&t.x<=max(a1.x,a2.x)&&t.y>=min(a1.y,a2.y)&&t.y<=max(a1.y,a2.y))//不规范相交
    {
        return 1;
    }
    else//不相交
    {
        return 0;
    }
}
signed main()
{
    int T;
    cin>>T;
    while(T--)
    {
        d a1,a2,b1,b2;
        cin>>a1.x>>a1.y>>a2.x>>a2.y>>b1.x>>b1.y>>b2.x>>b2.y;
        if((a1.y-a2.y)*(b1.x-b2.x)==(a1.x-a2.x)*(b1.y-b2.y))//平行
        {
            if(a1.x-a2.x==0)//斜率不存在
            {
                if(a1.x==b1.x)//共线
                {
                    if(judge(a1,a1,a2,b1,b2)||judge(a2,a1,a2,b1,b2))//有重叠
                    {
                        cout<<"YES"<<endl;
                    }
                    else//不重叠
                    {
                        cout<<"NO"<<endl;
                    }
                }
                else//不共线
                {
                    cout<<"NO"<<endl;
                }
            }
            else//斜率存在
            {
                double bb1=a1.y-(a1.y-a2.y)/(a1.x-a2.x)*a1.x;
                double bb2=b1.y-(b1.y-b2.y)/(b1.x-b2.x)*b1.x;
                if(bb1==bb2)//共线
                {
                    if(judge(a1,a1,a2,b1,b2)||judge(a2,a1,a2,b1,b2))//有重叠
                    {
                        cout<<"YES"<<endl;
                    }
                    else//不重叠
                    {
                        cout<<"NO"<<endl;
                    }
                }
                else//不共线
                {
                    cout<<"NO"<<endl;
                }
            }
        }
        else//不平行
        {
            if(a1.x==a2.x)//a斜率不存在
            {
                double bb2=b1.y-(b1.y-b2.y)/(b1.x-b2.x)*b1.x;
                d t={a1.x,(b1.y-b2.y)/(b1.x-b2.x)*a1.x+bb2};
                if(judge(t,a1,a2,b1,b2)==2)//规范相交
                {
                    printf("YES (%.3f,%.3f)\n",t.x,t.y);
                }
                else if(judge(t,a1,a2,b1,b2)==1)//不规范相交
                {
                    cout<<"YES"<<endl;
                }
                else//不相交
                {
                    cout<<"NO"<<endl;
                }
            }
            else if(b1.x==b2.x)//b斜率不存在
            {
                double bb1=a1.y-(a1.y-a2.y)/(a1.x-a2.x)*a1.x;
                d t={b1.x,(a1.y-a2.y)/(a1.x-a2.x)*b1.x+bb1};
                if(judge(t,a1,a2,b1,b2)==2)//规范相交
                {
                    printf("YES (%.3f,%.3f)\n",t.x,t.y);
                }
                else if(judge(t,a1,a2,b1,b2)==1)//不规范相交
                {
                    cout<<"YES"<<endl;
                }
                else//不相交
                {
                    cout<<"NO"<<endl;
                }
            }
            else//斜率都存在
            {
                double bb1=a1.y-(a1.y-a2.y)/(a1.x-a2.x)*a1.x;
                double bb2=b1.y-(b1.y-b2.y)/(b1.x-b2.x)*b1.x;
                double k1=(a1.y-a2.y)/(a1.x-a2.x);
                double k2=(b1.y-b2.y)/(b1.x-b2.x);
                d t;
                t.x=(bb2-bb1)/(k1-k2);
                t.y=k1*t.x+bb1;
                if(judge(t,a1,a2,b1,b2)==2)//规范相交
                {
                    printf("YES (%.3f,%.3f)\n",t.x,t.y);
                }
                else if(judge(t,a1,a2,b1,b2)==1)//不规范相交
                {
                    cout<<"YES"<<endl;
                }
                else//不相交
                {
                    cout<<"NO"<<endl;
                }
            }
        }
    }
}

 

标签:线段,相交,a1,a2,b1,b2
From: https://www.cnblogs.com/sleepaday/p/17625293.html

相关文章

  • 「学习笔记」线段树优化建图
    在建图连边的过程中,我们时常会碰到这种题目,一个点向一段连续的区间中的点连边或者一个连续的区间向一个点连边,如果我们真的一条一条连过去,那一旦点的数量多了复杂度就爆炸了,这里就需要用线段树的区间性质来优化我们的建图了。那棵线段树大概长这个样子。到时候加边的时候是这个......
  • p5两链表相交问题和二叉树
    (本文大多从杀戒之声处来,就想着自己方便看)两链表相交问题所谓相交,是指两链表有某一内存地址相同,则为相交,判断有环无环,哈希表(set),第一次相同(单向链表)快慢指针,快走2,慢走1,快慢指针第一次相遇后,将快指针返回头节点,慢指针不动,快改为走1,看快慢节点是否能相遇,有环则一定会在入环节......
  • 线段树
    线段树线段树是一种二叉树形数据结构,用于解决区间查询和区间修改问题。它将一个数组划分为若干个连续的区间,每个区间对应线段树的一个节点。通过递归地构建线段树,我们可以在O(logn)的时间复杂度内完成区间查询和区间修改操作。原理线段树的构建过程如下:将原数组划分为n个子......
  • 在不完全重合的情况下,判断线经过另一线段的方法
    importlogginglogging.basicConfig(level=logging.INFO,format='%(asctime)s-%(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s',datefmt='%Y-%m-%d%H:%M:%S')importnumpyasnpfromshapely.......
  • 【数据结构】线段树
    例题1:给定一个正整数数列,每一个数都在添加操作:向序列后添加一个数,序列长度变成;询问操作:询问这个序列中最后程序运行的最开始,整数序列为空。一共要对整数序列进行次操作。写一个程序,读入操作的序列,并输出询问操作的答案。数据范围这道题看第一眼:暴力,再看一眼:爆炸(bushiTLE。......
  • 【学习笔记】线段树分治
    定义线段树分治是一种解决一类有插入、删除和整体查询操作的问题的方法。它是一种离线做法,通过在线段树上记录操作的时间区间来处理修改对询问的影响。每个操作被看作一个时间区间的修改,并在线段树上进行标记。然后通过深度优先搜索(DFS)依次执行这些操作,直到根节点来回答查询,并在......
  • 线段树的一些延伸
    一.动态开点线段树简介虽然思路简单,但对于一个习惯数组写法的人,这是一个比较难受的东西。动态开点一般是用来解决空间上的问题的。一般来说,普通的线段树是直接将一颗完整的线段建出来,但如碰到数据范围大或卡空间的时候,我们就只能在我们需要的时候再建,这个就叫做动态开点。(类似......
  • 160. 相交链表
    给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。图示两个链表在节点 c1 开始相交:题目数据 保证 整个链式结构中不存在环。示例1:输入:intersectVal=8,listA=[4,1,8,4,5],listB=[5,6,1,8,......
  • ABC245E Wrapping Chocolate [线段树二分]
    也许更好的阅读体验\(\mathcal{Description}\)\(n\)个物品有长和宽,\(m\)个盒子也有长和宽,一个盒子最多可以装一个物品,问\(n\)个物品能否都放进盒子,物品和盒子不能旋转\(\mathcal{Solution}\)先离散化长和宽,将物品和盒子按照长从大到小排序考虑到当前物品时将所有长大于等于当......
  • 线段树补充
    线段树补充线段树维护矩阵和矩阵快速幂和普通快速幂同理intM;structmatrix{ llx[M+1][M+1]; matrix(){ memset(x,0,sizeof(x)); }};matrixmultiply(matrix&a,matrix&b){ matrixc; for(inti=1;i<=M;i++) for(intj=1;j<=M;j++) for(intk=1;k<=......