1. 程式人生 > >51nod1264線段相交

51nod1264線段相交

題意:

解題思路:

剛開始想了個思路 算斜率判斷相交  然後發現需要特判的情況很多,斜率為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;
}