蓝桥杯 | 直线 问题 | python
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上, 那么这些点中任意两点确定的直线是同一条。
给定平面上 2 × 3 个整点 (x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z,即横坐标是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数的点。这些点一共确定了 11 条不同的直线。
给定平面上 20×21 个整点(x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z,即横坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 20 (包含 0 和 20) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。
运行限制
最大运行时间:1s
最大运行内存: 128M
2 × 3 个整点:
- 方案一
import os
import sys
class Line(object): # 直线类
# 用起点和终点坐标表示直线有重复不方便,还可以记录直线的斜率和截距
def __init__(self): # 初始化函数
self.k = 0 # 斜率
self.b = 0 # 截距
def __lt__(self, t): # L.sort()调用
if self.k != t.k: # 如果斜率不同,斜率小的排前面
return self.k < t.k
return self.b < t.b # 如果斜率相同,截距小的排前面
N = 200000 # 取大数,后面切片
l = [Line() for _ in range(N)] # 列表每个元素都是一个直线对象
n = 0 # 索引
for x1 in range(0, 20): # 遍历所有的起点和终点
for y1 in range(0, 21):
for x2 in range(0, 20):
for y2 in range(0, 21):
if x1 != x2: # x坐标不相同,k存在
k = float((y2 - y1)) / (x2 - x1) # 斜率
b = float(y2 - k * x2) # 截距
l[n].k = k # 开始n=0,赋值索引=0(第一个)直线对象
l[n].b = b
n += 1 # 赋值下一个索引的直线对象
# 四层循环完,除了垂直的直线,都存到l里,一共存了n个直线对象
L = l[0: n] # 切片存入L
# 对所有直线去重
L.sort() # 排序(方便去重),调用__lt__比较直线大小
res = 1 # 索引=0的直线先找到一条
for i in range(1, n): # 索引=1到n-1
# 比较浮点型的不同
if abs(L[i].k - L[i - 1].k) > 1e-8 or abs(L[i].b - L[i - 1].b) > 1e-8: # 斜率不同 or 截距不同
res += 1 # 相同直线过滤掉,不同直线累加1
print(res + 20) # 加上x坐标相同,k不存在的垂直直线(0到19共20条)
- 方案二
'''
方案一利用排序去重耗费时间太长,方案二利用集合结构去重不超过时间限制
'''
import os
import sys
# 请在此输入您的代码
xList=[i for i in range(20)]
yList=[i for i in range(21)]
points=[(x,y) for x in xList for y in yList] # 所有整数点,元组类型
# print(points)
s=set() # 利用集合结构去重
def getLine(p,q): # 集合中任意两点p(x1,y1),q(x2,y2)
k=(q[1]-p[1])/(q[0]-p[0]) # 斜率
b=q[1]-q[0]*k # 截距
return round(k,8),round(b,8) # 返回元组(斜率,截距)
for p in points:
for q in points: # 遍历集合中所有起点和终点
if p!=q and p[0]!=q[0]: # 两点不同且x坐标不同,排除垂直直线
s.add(getLine(p,q)) # 得到一个元组就加入集合里,自动去重
print(len(s)+20)