# 1030: 线段相交

[状态] [提交] [命题人:外部导入]

0 1 1 1
1 0 2 1
1 0 2 1
0 1 2 0
0 0 0 1
1 0 0 0

no
yes
yes

``````#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class Point {
public:
int x, y;
Point(int xx, int yy) :x(xx), y(yy) {}
};

int crossMul(Point& p1, Point& p2) {//两个向量叉乘
return p1.x * p2.y - p1.y * p2.x;
}

int main() {
int xa, ya, xb, yb, xc, yc, xd, yd;
while (cin >> xa >> ya >> xb >> yb >> xc >> yc >> xd >> yd) {
Point A(xa, ya);
Point B(xb, yb);
Point C(xc, yc);
Point D(xd, yd);
//这里向量也同样用Point类表示

//特殊情况（判断两条线段平行）
Point AB(xb - xa, yb - ya);
Point CD(xd - xc, yd - yc);
Point BC(xc - xb, yc - yb);
if (crossMul(AB, CD) == 0) {
//平行的情况分共线和不共线
//判断是否共线，两条线段选一个点组成向量，和原来任一线段如果平行，说明两线段共线
if (crossMul(BC, AB) == 0) {
//4种情况
//1.正向判断
if ((min(A.x, B.x) < min(C.x, D.x) && max(A.x, B.x) >= min(C.x, D.x))
|| (min(C.x, D.x) < min(A.x, B.x) && max(C.x, D.x) >= min(A.x, B.x))
|| (min(A.y, B.y) < min(C.y, D.y) && max(A.y, B.y) >= min(C.y, D.y))
|| (min(C.y, D.y) < min(A.y, B.y) && max(C.y, D.y) >= min(A.y, B.y))) {
cout << "yes" << endl;
continue;
}
else {
cout << "no" << endl;
continue;
}

//2.反向判断
//if (max(A.x, B.x) < min(C.x, D.x) || max(A.y, B.y) < min(C.y, D.y)
//	|| max(C.x, D.x) < min(A.x, B.x) || max(C.y, D.y) < min(A.y, B.y)) {
//	cout << "no" << endl;
//	continue;
//}
//else {
//	cout << "yes" << endl;
//	continue;
//}
}
else {
cout << "no" << endl;
continue;
}
}

//判断C和D是否在AB所在的直线的两边（下面的注释只是为了避免重复声明）
Point AC(xc - xa, yc - ya);
Point AD(xd - xa, yd - ya);
//Point AB(xb - xa, yb - ya);

//判断A和B是否在CD所在直线的两边
//Point AC(xc - xa, yc - ya);
//Point BC(xc - xb, yc - yb);
//Point CD(xd - xc, yd - yc);
//判断
bool flag1 = false;
bool flag2 = false;
if (crossMul(AC, AB) * crossMul(AD, AB) <= 0) {//异号（等于0是只有一个点相交的情况）
flag1 = true;
}
if (crossMul(AC, CD) * crossMul(BC, CD) <= 0) {//异号
flag2 = true;
}
//同时满足说明两线段相交，否则不相交
if (flag1 && flag2)
cout << "yes" << endl;
else
cout << "no" << endl;
}
return 0;
}
``````