1030: 线段相交
时间限制: 1 Sec 内存限制: 256 MB
提交: 87 解决: 13
[状态] [提交] [命题人:外部导入]
题目描述
输入线段AB、CD的两端点,判断两线段是否相交(包含端点)。
输入
有多组数据,每组数据两行,第一行四个整数,分别表示A、B两点坐标,第二行四个整数,分别表示C、D两点坐标。
输出
如果线段AB与线段CD相交,输出yes,否则输出no。
样例输入 Copy
0 1 1 1
1 0 2 1
1 0 2 1
0 1 2 0
0 0 0 1
1 0 0 0
样例输出 Copy
no
yes
yes
思路讲解:
https://www.cnblogs.com/tuyang1129/p/9390376.html
三种方法:
https://blog.csdn.net/yegshun/article/details/78273471?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
#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;
}