线段相交问题(向量叉乘)

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;
}
发布了25 篇原创文章 · 获赞 17 · 访问量 707

猜你喜欢

转载自blog.csdn.net/mu_mu_mu_mu_mu/article/details/105082611