题目大意
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
在平面直角坐标系中,两点可以确定一条直线。
给定平面上 20×21 个整点 {(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},即横 坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 2020 (包含 0 和 20) 之 间的整数的点。
请问这些点一共确定了多少条不同的直线。
解题思路
在平面直角坐标系中,俩点可以确定一条直线,那俩点有四个坐标值,我们不太好维护四个坐标值是否重复。
我们知道直线的表示方式中,除了俩点式,还有点斜式,点斜式的话, 一个点俩个坐标值和一个斜率值,三个值来确定唯一性,虽然不太好写但是还是勉强能跑出来。
更进一步,如果那个点是在 x 轴或者 y 轴上,那么一个坐标就恒定为 0, 只要维护另一个坐标值(其实就是截距啦)和斜率就好了,简单 map 维护一下,注意枚举的斜率不存在的情况呢。
最终答案:40257。
参考代码(Python):
# 方法一: '超过时间限制'
class Line(object):
def __init__(self):
self.k = 0
self.b = 0
def __lt__(self, t):
if self.k != t.k: # 当两条直线斜率不等时
return self.k < t.k # 斜率小的排前面(排序)
return self.b < t.b # 斜率相等时,截距小的排前面
N = 200000
n = 0
l = [Line() for _ in range(N)]
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:
k = float((y2 - y1)) / (x2 - x1)
b = float(y2 - k * x2)
l[n].k = k
l[n].b = b
n += 1
L = l[0: n] # 切片
L.sort() # 排序(耗时),排好序再比较斜率和截距不会出错。解决方法-用集合的思想。
res = 1
for i in range(1, n): # 去重
if abs(L[i].k - L[i - 1].k) > 1e-8 or abs(L[i].b - L[i - 1].b) > 1e-8:
res += 1 # 斜率和截距都是浮点数,所以比较一个比较小的浮点数1e8判断是否相同
print(res + 20) # 20指垂直的直线,即斜率为无穷
# 方法二: # 推荐
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]
s = set() # 定义查重集合,集合中元素不可以重复
def getLine(p, q):
k = (q[1] - p[1]) / (q[0] - p[0])
b = q[1] - q[0] * k
return round(k, 8), round(b, 8) # 返回元组,四舍五入保留8位小数
for p in points:
for q in points:
if p != q and p[0] != q[0]: # 去除重复点和横坐标相同点
s.add(getLine(p, q)) # 集合,满足去重的功能
print(len(s) + 20) # 20指垂直的直线,即斜率为无穷
参考代码仅供学习记录用,各位有更好的想法欢迎评论区补充。