给定线段P1P2(P1和P2是线段的两端点,且不重合)、P3P4(P3和P4是线段的两端点,且不重合),判断P1P2和P3P4是否相交。P1P2和P3P4相交,即指存在一个点P,它既落在P1P2上又落在P3P4上(含线段的端点)。
输入数据有多组,第一行为测试数据的组数N,下面包括2N行,每组测试数据含2行,第一行为P1P2的坐标值,第二行为P3P4的坐标值,比如下面的数据
表示P1、P2、P3、P4的坐标分别为:P1(0,0),P2(1,1),P3(2,2),P4(3,3)
判断每组数据中的线段P1P2和P3P4是否相交,如果相交输出YES,否则输出NO。每组数据输出占一行。
2
0 0 1 1
2 2 3 3
0 0 2 0
0 0 1 3
NO
YES
两线段相交分为“规范相交”和“非规范相交”。 “规范相交”指的是两条线段恰有唯一一个不是端点的公共点;而如果一条线段的一个端点在另一条线段上,或者两条线段部分重合,则视为“非规范相交”,本题是“非规范相交”。
定义点坐标类型时需用double
2012级新生练习赛 3
sunshine@Hrbust
给你两个线段,判断是否相交
线段相交定理运用
另一条线段的两个端点都在当前线段的顺时针和逆时针方向
这个是非范式相交,注意情况要考虑完全
#include
using namespace std;
#define EPS 1e-10
class Point{
public:
double x,y;
Point(int x=0,int y=0):x(x),y(y){}
Point operator + (Point a){return Point(x+a.x,y+a.y);}
Point operator - (Point b){return Point(x-b.x,y-b.y);}
double norm(void){return x*x + y*y;}
};
typedef Point Vector;
double cross(Vector a,Vector b)
{
return a.x*b.y - a.y*b.x;
}
double dot(Vector a,Vector b)
{
return a.x*b.x + a.y*b.y;
}
int ccw(Point p0,Point p1,Point p2)
{
Vector a = p1 - p0;
Vector b = p2 - p0;
if(cross(a,b)<-EPS) return -1;
if(cross(a,b)>EPS) return 1;
if(dot(a,b)<-EPS) return 2;
if(a.norm() < b.norm()) return -2;
return 0;
}
bool isinter(Point a,Point b,Point c,Point d)
{
if(ccw(a,b,c)*ccw(a,b,d)<=0&&ccw(c,d,a)*ccw(c,d,b)<=0) return true;
return false;
}
void solve(void)
{
int t;
scanf("%d",&t);
while(t--)
{
Point a,b,c,d;
cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y;
if(isinter(a,b,c,d)) cout<<"YES"<else cout<<"NO"<int main(void)
{
solve();
return 0;
}