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