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、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;
};
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;
}