51nod 1264 线段相交

写得很复杂,还好一遍过了。

方法是直接根据线段两点,得到直线方程,联立方程组求交点,然后看交点是否在两线段之间。注意平行、位于同一直线时的情况就可以了。


#include<bits/stdc++.h>
using namespace std;
#define LL long long
struct P
{
    double x,y;
};
int cmp(double x)
{
    if(fabs(x)<1e-15) return 0;
    if(x>0) return 1;
    return -1;
}

bool get(P a1,P b1,double &k,double &b)//求直线方程
{
    if(cmp(a1.x-b1.x)==0) return 0;//垂直x轴
    k=(a1.y-b1.y)/(a1.x-b1.x);
    b=a1.y-k*a1.x;
    return 1;
}
bool judge(P a1,P b1,P a2,P b2)
{
    double k1,m1,k2,m2;
    if(!get(a1,b1,k1,m1))
    {
        if(!get(a2,b2,k2,m2))       //均垂直x轴
        {
            if(cmp(a1.x-a2.x)!=0) return 0; //平行
            double max1=max(a1.y,b1.y),max2=max(a2.y,b2.y);
            double min1=min(a1.y,b1.y),min2=min(a2.y,b2.y);
            if(cmp(max2-min1)>=0&&cmp(max1-max2)>=0) return 1;
            if(cmp(max1-min2)>=0&&cmp(max2-max1)>=0) return 1;
            return 0;
        }
        else
        {
            double max2=max(a2.x,b2.x),min2=min(a2.x,b2.x);
            double maxy=max(a1.y,b1.y),miny=min(a1.y,b1.y);
            if(cmp(a1.x-min2)>=0&&cmp(a1.x-max2)<=0)
            {
                double ty=k2*a1.x+m2;
                if(cmp(ty-miny)>=0&&cmp(ty-maxy)<=0) return 1;
                return 0;
            }
            return 0;
        }
    }
    else if(!get(a2,b2,k2,m2))
    {
            double max1=max(a1.x,b1.x),min1=min(a1.x,b1.x);
            double maxy=max(a2.y,b2.y),miny=min(a2.y,b2.y);
            if(cmp(a2.x-min1)>=0&&cmp(a2.x-max1)<=0)
            {
                double ty=k1*a2.x+m1;
                if(cmp(ty-miny)>=0&&cmp(ty-maxy)<=0) return 1;
                return 0;
            }
            return 0;
    }
    else
    {
        double x,y;
        if(cmp(k1-k2)==0)
        {
            if(cmp(m1-m2)==0)   //位于同一直线
            {
                double max1=max(a1.y,b1.y),max2=max(a2.y,b2.y);
                double min1=min(a1.y,b1.y),min2=min(a2.y,b2.y);
                if(cmp(max2-min1)>=0&&cmp(max1-max2)>=0) return 1;
                if(cmp(max1-min2)>=0&&cmp(max2-max1)>=0) return 1;
                return 0;
            }
            else return 0;      //平行
        }
        x=(m2-m1)/(k1-k2);
        y=k1*x+m1;
        double max1=max(a1.y,b1.y),max2=max(a2.y,b2.y);
        double min1=min(a1.y,b1.y),min2=min(a2.y,b2.y);

        if(cmp(y-min1)>=0&&cmp(max1-y)>=0&&cmp(y-min2)>=0&&cmp(max2-y)>=0) return 1;
        return 0;
    }
}
int main()
{
    int t;
    P a1,b1,a2,b2;
    cin>>t;
    while(t--)
    {
       cin>>a1.x>>a1.y>>b1.x>>b1.y>>a2.x>>a2.y>>b2.x>>b2.y;
       if(judge(a1,b1,a2,b2)) puts("Yes");
       else puts("No");
    }
    return 0;
}


更加方便的解法是利用向量。


http://www.cnblogs.com/zhangchaoyang/articles/2668562.html



你可能感兴趣的:(51nod 1264 线段相交)