版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lnotime/article/details/82313355
Python3.6.3
如下图所示,平面上有一些点,需要将所有点连起来,使任何一个点都可以和其他点连通(直接或间接),且连接线段长度总和最短。
例:下面的四个点,相互连通,并且总长度是最短的。
思路:共有n个点,最短连线集合f(n)一定存在。
假设有m (1≤m<n)个点,它们的最短连线集合是f(m),并且满足在f(n)中这m个点的连线也可以是f(m)。
计算剩余n-m个点与m个点的距离,最短的那条就是要求的下一条连线。
import math
from typing import List
def point_connect(pots: List[list]):
"""
完成所有点的连接,返回所有线段的list(线段中包含两个点的索引)和最短路径值,要求所有线路之和最短。
例如输入 pots = [[0, 0], [2, 0], [3, 2], [3, -2]]
返回 paths = [[0, 1], [1, 2], [1, 3]], length =
"""
l = len(pots)
if l <= 1:
return [], 0
con = [pots[0]] # 已经连线的点集,先随便放一个点进去
not_con = pots[1:] # 还没连线的点集
paths = [] # 所有连线
length_total = 0 # 总连线长度
for _ in range(l - 1): # 共 l-1 条连线
# 得到下一条连线的两点a、b 及其距离length_ab
a, b = con[0], not_con[0] # 先任意选两个点
length_ab = math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2)
for m in con:
for n in not_con:
lg = math.sqrt((m[0] - n[0]) ** 2 + (m[1] - n[1]) ** 2)
if lg < length_ab: # 如果有更短的
length_ab = lg
a, b = m, n
# 记录
paths.append([pots.index(a), pots.index(b)]) # 记录连线ab
con.append(b) # 已连接点集中记录点b
not_con.remove(b) # 未连接点集中删除点b
length_total += length_ab # 记录总长度
return paths, length_total
1·n+2·(n-1)+3(n-2)+…+n·1=(1/6)[n·(n+1)(n+2)]
三层循环,一共是(1/6)[(n-1)·n·(n+1)]次操作,所以时间复杂度O(n^3);空间复杂度O(n)
test:
import matplotlib.pyplot as plt
import random
import math
from typing import List
from print_time import print_time as pt
def point_connect(pots: List[list]):
pass
def draw(pots: List[list], paths: List[list], l, h):
"""把点和路径画出来"""
plt.figure(figsize=(10, 10))
for a, b in paths:
x = [pots[a][0], pots[b][0]]
y = [pots[a][1], pots[b][1]]
plt.plot(x, y, marker='o')
plt.xticks(range(math.floor(l), math.ceil(h) + 1))
plt.yticks(range(math.floor(l), math.ceil(h) + 1))
plt.grid(linestyle='--')
plt.savefig('pointTest.png')
plt.show()
@pt
def _test():
n = 200 # 数量
l, h = -5, 5 # 范围上下限
pots = set()
while len(pots) < n:
pots.add((random.uniform(l, h), random.uniform(l, h)))
pots = list(map(list,pots)) # 点集
# print(sorted(pots))
paths, length_total = point_connect(pots) # 求得路径
# print(paths)
print(len(paths), length_total)
draw(pots, paths, l, h) # 画图查看
if __name__ == '__main__':
_test()
# 结果:
# 199 94.308326578364
# >>>RUN TIME: <_test> : 1.4082343578338623