题意:给你两条线段的四个端点,判断两条线段是否相交,相交并求交点。
这题不严谨,还有两条线段重合的部分,如果重合,交点有无数个,而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;
}
}