CSP-202006-1-线性分类器
解题思路
1.数据结构:
- 代码使用了一个名为
MyPoint
的结构体来表示空间中的点。这个结构体包含三个属性:x
和y
表示点的坐标,type
表示点的类型。点的类型用整数表示,类型 ‘A’ 用 0 表示,类型 ‘B’ 用 1 表示。这种方式简化了后续的逻辑判断。
2.输入处理:
- 程序首先读取两个整数
n
和m
。n
是给定的点的总数,m
是需要处理的查询(即直线)的总数。 - 对于每一个点,程序通过输入读取其坐标 (
x
,y
) 和类型 (type
)。类型是以字符形式给出的,在存储到MyPoint
结构体中时,会转换为整数(‘A’ 转换为 0,‘B’ 转换为 1)。 - 所有这些点被存储在一个名为
list
的vector<MyPoint>
容器中,便于后续遍历和分类。
3.处理查询:
- 对于每个查询(即每条直线),程序读取三个整数
t0
、t1
和t2
,这些整数定义了直线的方程t0 + t1 * x + t2 * y = 0
。 - 程序初始化两个集合
set0
和set1
,用于记录被当前直线分隔的两边各自存在哪些类型的点。 - 程序遍历所有点,对于每个点,根据直线方程计算
t0 + t1 * x + t2 * y
的值:- 如果结果大于0,表示该点在直线的一侧,程序将这个点的类型添加到
set0
中。 - 如果结果小于或等于0,表示该点在直线的另一侧,程序将这个点的类型添加到
set1
中。
- 如果结果大于0,表示该点在直线的一侧,程序将这个点的类型添加到
- 这样,每个集合中包含了相应侧的点的类型,可以有0、1或2种类型(因为点的类型只有 ‘A’ 和 ‘B’)。
4.输出结果:
- 在对所有点进行分类后,程序检查
set0
和set1
中包含的点的类型。 - 如果任一集合中同时包含类型 ‘A’ 和类型 ‘B’ 的点(即该集合的大小等于2),这意味着当前的直线不能将两种类型的点完全分开,因此程序输出 “No”。
- 如果每个集合中都只包含一种类型的点(或者一个集合为空),这意味着当前直线能够将类型 ‘A’ 和类型 ‘B’ 的点分开,因此程序输出 “Yes”。
完整代码
#include <iostream>
#include <vector>
#include <set>
using namespace std;struct MyPoint
{long long x, y, type; // A-0 B-1
};long long n, m, x, y, t0, t1, t2;
char type;
vector<MyPoint>list;int main() {cin >> n >> m;for (size_t i = 0; i < n; i++){cin >> x >> y >> type;if (type == 'A') list.push_back({ x,y,0 });else if (type == 'B') list.push_back({ x,y,1 });}for (size_t i = 0; i < m; i++){cin >> t0 >> t1 >> t2;set<long long>set0, set1;for (auto& it : list){if (t0 + t1 * it.x + t2 * it.y > 0) set0.insert(it.type);else set1.insert(it.type);}if (set0.size() == 2) cout << "No\n";else if (set1.size() == 2) cout << "No\n";else cout << "Yes\n";}return 0;
}