码题杯 射线的交 题型:分类讨论 难度:白银

18 阅读2分钟

码题集OJ-射线的交 (matiji.net)

思想

首先题目说了只有两条线垂直相交才算相交:

image.png image.png

那么本题相交的情况就只有四种: 向上的直线和向左的直线相交:

image.png

向上的直线和向右的直线相交:

image.png

向下的直线和向左的直线相交:

image.png

向下的直线和向右的直线相交:

image.png

我们针对每一种情况给出解决方案即可。

code

我们判断两条直线是否会相交,首先需要判断这两条直线是否垂直。向上的直线和向下的直线不会相交,向左的直线和向右的直线不会相交。因为我们需要划分一下阵营。

把向上的直线和向下的直线划为一类,向左的直线和向右的直线划为一类。

我们对四个方向做一个哈希处理,1,2代表上下,-1,-2代表左右。

这样两条边相乘小于0,我们就知道这是一条向上/向下的直线和一条向左/向右的直线,那么这两条直线就会垂直。

如果两条直线垂直了我们再去判断它们是否相交。

#include <bits/stdc++.h>
using namespace std;
int ans;
const int N = 510;

struct point {
	int x, y, type;
} p[N];

int n;

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		char op;
		cin >> p[i].x >> p[i].y >> op;
		switch (op) {
			case 'U':
				p[i].type = 1;
				break;
			case 'D':
				p[i].type = 2;
				break;
			case'L':
				p[i].type = -1;
				break;
			case 'R':
				p[i].type = -2;
			default:
				break;
		}
	}
	//判断一下两条直线是否垂直
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			if ((p[i].type * p[j].type) < 0) {
				point u = p[i], v = p[j];

				if (u.type < 0)
					swap(u, v); //让u维护UD
				if (
				    (u.type == 1 && v.type == -1 && v.x >= u.x && v.y >= u.y) || // UL
				    (u.type == 1 && v.type == -2 && v.x <= u.x && v.y >= u.y ) || //UR
				    (u.type == 2 && v.type == -1 && v.x >= u.x && v.y <= u.y) || //DL
				    (u.type == 2 && v.type == -2 && v.x <= u.x && v.y <= u.y) //DR
				)
					ans++;
			}
		}
	}

	cout << ans << endl;
	return 0;
}

image.png