题目
试题编号: | 202006-1 |
试题名称: | 线性分类器 |
时间限制: | 1.0s |
内存限制: | 512.0MB |
题目描述
考虑一个简单的二分类问题——将二维平面上的点分为 A 和 B 两类。
训练数据包含 n 个点,其中第 i 个点(1 ≤ i ≤ n)可以表示为一个三元组(xi1,yi1 ,typei),即该点的横坐标、纵坐标和类别。
在二维平面上,任意一条直线可以表示为θ0+θ1x+θ2y=0的形式,即由θ0、θ1和θ2三个参数确定该直线,且满足θ1和θ2不同时为 0。
基于这 n 个已知类别的点,我们想要在平面上找到一条直线作为一个线性分类器。具体来说,这条线要把训练数据中的 A、B两类点完美分隔开来,即一侧只有 A 类点、另一侧只有B类点。这样,对于任意一个的未知类别的点,我们就可以根据它是位于直线的哪一侧来预测它的类别了。
在本题中我们仅需要处理 m个如下查询∶给定一条直线,判断它是否能将训练数据中的 A、B 两类点完美分开。
输入格式
从标准输入读入数据。
输入共 n+m+1行。
第一行包含用空格分隔的两个正整数 n 和 m ,分别表示点和查询的个数。
第二行到第n+1行依次输入 n 个点的信息。第n+1行(1≤ i ≤ n)包含用空格分隔的三项xi、yi和typei,分别表示第 i 个点的横、纵坐标和类别,其中坐标为整数、类别为一个大写英文字母A或B。
第n+2行到第n+m+1行依次输入 m个查询。第j+n+1行(1≤ j ≤ m)包含用空格分隔的三个整数θ0、θ1和θ2,表示第j个查询中给定直线的三个参数。
输出格式
输出到标准输出。
输出共 m 行,每行输出一个字符串。
第 j 行(1≤ j ≤ m)输出的字符串对应第 j 个查询的结果∶ 如果给定直线可以完美分隔A、B两类点,则输出Yes; 否则输出No。
样例1输入
9 3
1 1 A
1 0 A
1 -1 A
2 2 B
2 3 B
0 1 A
3 1 B
1 3 B
2 0 A
0 2 -3
-3 0 2
-3 1 1
样例1输出
No
No
Yes
样例1 解释
只有第 3个查询给出的直线能将A、B两类点完美分隔。
子任务
输入数据保证不存在恰好落在给定直线上的点;
0< n ≤103、0< m ≤20,且A、B两类点的数量均不为0;
所有点的坐标和给定直线的三个参数均为整数,且绝对值≤106;
任意两个点的坐标不完全相同。
程序代码
# 输入n,m
n,m = input().split()
n = int(n)
m = int(m)
# A\B类测试点列表
pointsA = []
pointsB = []
# 输入测试点格式转换并加入列表
for i in range(n):
point = input().split()
point[0] = int(point[0])
point[1] = int(point[1])
if point[2] == 'A':
pointsA.append(point)
else:
pointsB.append(point)
# 直线参数列表
lines = []
# 输入直线参数格式转换并加入列表
for i in range(m):
line = input().split()
for j in range(3):
line[j] = int(line[j])
lines.append(line)
# 遍历直线参数列表 并统计在直线上方的A\B类点数目 判断并输出
for i in range(m):
c,a,b = lines[i]
sumA = 0
sumB = 0
# 统计在直线上方的A类点数目
for j in range(len(pointsA)):
x,y,tag = pointsA[j]
value = a * x + b * y + c
if value > 0:
sumA += 1
# 统计在直线上方的B类点数目
for j in range(len(pointsB)):
x,y,tag = pointsB[j]
value = a * x + b * y + c
if value > 0:
sumB += 1
# 判断条件为直线上方只有某一类点的全体
if (sumA == 0 and sumB == len(pointsB)) or (sumA == len(pointsA) and sumB == 0):
print("Yes")
else:
print("No")