Python 平面上的点的最短连线网

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lnotime/article/details/82313355

Python3.6.3

 如下图所示,平面上有一些点,需要将所有点连起来,使任何一个点都可以和其他点连通(直接或间接),且连接线段长度总和最短。

点

例:下面的四个点,相互连通,并且总长度是最短的。

4点

思路:共有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

pointTest

猜你喜欢

转载自blog.csdn.net/lnotime/article/details/82313355