nyoj 1132 promise me a medal(线段相交问题)

题意:给你两条线段的四个端点,判断两条线段是否相交,相交并求交点。

这题不严谨,还有两条线段重合的部分,如果重合,交点有无数个,而ac的代码仅输出了重合的端点。

///判断两直线相交方法:两条相交的线段必然相互跨立,简单的讲就是p1和p2两点位于L2的两侧且p3和p4两点位于L1的两侧,这样就可利用外积做出判断了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct point
{
    double x,y;
} a[4];
bool Equal(double f1, double f2)
{
    return (abs(f1 - f2) < 1e-4f);
}
bool operator==(const point &p1, const point &p2)///重载函数,用于判断两点是否相等
{
    return (Equal(p1.x, p2.x) && Equal(p1.y, p2.y));
}
bool operator>(const point &p1, const point &p2)///比较两点坐标大小,先比较x坐标,若相同则比较y坐标
{
    return (p1.x > p2.x || (Equal(p1.x, p2.x) && p1.y > p2.y));
}
double cross(point p1,point p2,point p3)
{
    return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
}
int main()
{
    int t;
    double k1,k2,k3,k4,b1,b2,x,y,D,D1,D2;
    cin>>t;
    while(t--)
    {
        for(int i=0; i<4; i++)
            cin>>a[i].x>>a[i].y;
        if(a[0]>a[1])
            swap(a[0],a[1]);
        if(a[2]>a[3])
            swap(a[2],a[3]);
            ///为方便运算,保证各线段的起点在前,终点在后。
        b1=(a[1].y-a[0].y)*a[0].x+(a[0].x-a[1].x)*a[0].y;
        b2=(a[3].y-a[2].y)*a[2].x+(a[2].x-a[3].x)*a[2].y;
        D=(a[1].x-a[0].x)*(a[3].y-a[2].y)-(a[3].x-a[2].x)*(a[1].y-a[0].y);
        D1=b2*(a[1].x-a[0].x)-b1*(a[3].x-a[2].x);
        D2=b2*(a[1].y-a[0].y)-b1*(a[3].y-a[2].y);
        x=D1/D;
        y=D2/D;
        ///以上是根据坐标求交点
        k1=cross(a[3],a[0],a[1]);
        k2=cross(a[2],a[0],a[1]);
        k3=cross(a[0],a[2],a[3]);
        k4=cross(a[1],a[2],a[3]);
        if(k1*k2==0&&k3*k4==0)///共线
        {
            if(a[1]==a[2])
                printf("yes %.1lf %.1lf\n",a[1].x,a[1].y);
            else if(a[3]==a[0])
                printf("yes %.1lf %.1lf\n",a[3].x,a[3].y);
                else if(a[1]>a[2])
                    printf("yes %.1lf %.1lf\n",a[1].x,a[1].y);
                else if(a[3]>a[0])
                    printf("yes %.1lf %.1lf\n",a[3].x,a[3].y);
            else
                cout<<"no"<<endl;
        }
        else if(k1*k2<=0&&k3*k4<=0)///相交
        {
            printf("yes %.1lf %.1lf\n",x,y);
        }
        else
            cout<<"no"<<endl;

    }

}


你可能感兴趣的:(ACM,几何,nyoj解题报告)