51nod1264线段相交

版权声明:原创文章如需转载请注明出处 https://blog.csdn.net/holly_Z_P_F/article/details/84792291

题意:

解题思路:

刚开始想了个思路 算斜率判断相交  然后发现需要特判的情况很多,斜率为0, 斜率不存在 ,一个有斜率,一个没斜率,一个斜率是0,一个不是0,两个都是0.。。。。。简直要烦死,程序改了又改,最终写了六层大嵌套if else判断语句  实在写不下去了  百度一搜 果然  又是万恶的线性代数 叉乘!

唉 早该想到的 上次写三角形顺序用的就是叉乘

  做法:

两个线段 四个点 判断线段是否相交  ---->就是判断一条线段和一个直线是否相交

如果 c和d在直线 ab 的两侧  那么 线段cd 一定和直线 ab 相交

同理 如果a和b在直线 cd 两侧 那么直线cd一定和线段ab相交

而这两个条件同时成立  就说明 线段ab和线段cd一定相交

那如何判断两个点是否在直线的两侧呢

叉乘

根据右手定则

向量ab 叉乘 向量bc      与    向量ab 叉乘 向量bd   符号相反  说明c d在ab两侧  符号相同 说明在同一侧   

好了 做两次叉乘 问题就解决了

作为一个线性代数不好的人 这里记录下叉乘的做法

各个点坐标   a(a1,a2)    b(b1,b2)   c(c1,c2)   d(d1,d2)

向量ab   (b1-a1 , b2-a2, 0)
向量bc   (c1-b1 ,  c2-b2, 0)
向量bd   (d1-b1 , d2-b2, 0)

ab叉乘bc  

|     i           j       k  |

|b1-a1   b2-a2   0  |

|c1-b1   c2-b2   0  |

就等于               k*     就等于k* (b1-a1)*(c2-b2)-(c1-b1)*(b2-a2)

代码如下

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long ll;
int T;
bool cc(double a1,double a2,double b1,double b2,double c1,double c2,double d1,double d2){
    //向量ab   (b1-a1,b2-a2,0)
    //向量bc   (c1-b1,c2-b2,0)
    //向量bd   (d1-b1,d2-b2,0)
    
    double x=(b1-a1)*(c2-b2)-(c1-b1)*(b2-a2); //ab bc 叉乘
    double y=(b1-a1)*(d2-b2)-(d1-b1)*(b2-a2); //ab bd 叉乘
    if(x*y<=0)return true;
    else return false;
}
int main(){
    scanf("%d",&T);
    double ax,ay,bx,by,cx,cy,dx,dy;
    while(T--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy);
        if(cc(ax,ay,bx,by,cx,cy,dx,dy)&&cc(cx,cy,dx,dy,ax,ay,bx,by)){
            printf("Yes\n");
        }
        else{
            printf("No\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/holly_Z_P_F/article/details/84792291
今日推荐