给出平面上两条线段的两个端点,判断这两条线段是否相交(有一个公共点或有部分重合认为相交)。 如果相交,输出"Yes",否则输出"No"。
Input
第1行:一个数T,表示输入的测试数量(1 <= T <= 1000) 第2 - T + 1行:每行8个数,x1,y1,x2,y2,x3,y3,x4,y4。(-10^8 <= xi, yi <= 10^8) (直线1的两个端点为x1,y1 | x2, y2,直线2的两个端点为x3,y3 | x4, y4)
Output
输出共T行,如果相交输出"Yes",否则输出"No"。
Input示例
2 1 2 2 1 0 0 2 2 -1 1 1 1 0 0 1 -1
Output示例
Yes No
#include<stdio.h>
#include<algorithm>
using namespace std;int t;
struct point{
double x;
double y;
};
point a,b,c,d,ab,cd;
int judge()//判断是否重合
{
if(ab.x==0&&(a.x==c.x||a.x==d.x||b.x==c.x||b.x==d.x))
return 1;//斜率不存在时的重合
double k=cd.y/cd.x;
double b=c.y-cd.y*c.x/cd.x;
if(a.y==k*a.x+b)
return 1;
return 0;
}
int check()
{
double k1,k2,b1,b2;
double maxx,minx,maxy,miny;
ab={(b.x-a.x),(b.y-a.y)};
cd={(d.x-c.x),(d.y-c.y)};
if(ab.x*cd.y-ab.y*cd.x==0)
{
if(judge()) //判断是否重合
return 1;
else
return 0;
}
//斜率不存在
if(ab.x==0)
{
k2=cd.y/cd.x;
b2=c.y-cd.y*c.x/cd.x;
maxy=max(a.y,b.y);
miny=min(a.y,b.y);
if(k2*a.x+b2>=miny&&k2*a.x+b2<=maxy)
return 1;
else
return 0;
}
else if(cd.x==0)
{
k1=ab.y/ab.x;
b1=a.y-ab.y*a.x/ab.x;
maxy=max(c.y,d.y);
miny=min(c.y,d.y);
if(k1*c.x+b1>=miny&&k1*c.x+b1<=maxy)
return 1;
else
return 0;
}
else if(ab.x!=0&&cd.x!=0)
{
// puts("debug");
k2=cd.y/cd.x;
b2=c.y-cd.y*c.x/cd.x;
k1=ab.y/ab.x;
b1=a.y-ab.y*a.x/ab.x;
// printf("%lf %lf %lf %lf\n",k1,b1,k2,b2);
if(k1==k2&&b1==b2)
return 1;
double xx=(b2-b1)/(k1-k2);
double min1,min2,max1,max2;
min1=min(a.x,b.x);
max1=max(a.x,b.x);
min2=min(c.x,d.x);
max2=max(c.x,d.x);
minx=max(min1,min2);
maxx=min(max1,max2);
//printf("%lf %lf\n",minx,maxx);
if(xx>=minx&&xx<=maxx)
return 1;
else
return 0;
}
else
return 1;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%lf %lf %lf %lf %lf %lf %lf %lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&d.x,&d.y);
if(check()==1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}