python动态演示分治法解决最近对问题

我真是个菜鸡。又搞了一天作业。感觉python确实没有C好写算法,很多地方不严密。。。

最近对,就是n个点中找最近的一对点。

分治法,主要就是递归,把一个问题分分分分分分分,然后合合合合合合合合合。

思想很简单,但是处理了几个小时的语法,类型错误问题,还好会点调试,要不今天都不一定能找出自己写的细节错误。

废话扯完,来看看算法吧。

核心函数,有2个参数,数组的左开头和右开头。

首先判断长度,根据情况进行计算距离,向下分治(也就是递归)。

然后比较距离,将小的那个存储到一个变量。

最后就是判断中线两边点的距离,和上一个最小值进行比较。

就是这么简单。给出代码。

import random
import math
import matplotlib.pyplot as p

input = int(input('输入生成点的数量:'))
dot = [[0]*3 for i in range(input)]
mindis = 1000 * 1000
fg = p.figure()
cn = fg.add_subplot(1, 1, 1)
cn.set_xlim(0, 1000)
cn.set_ylim(0, 1000)
p.ion()
a = [1000, 1000]
b = [0, 0]
x = []
y = []
for i in range(input):
    dot[i][0] = random.randrange(1000)
    dot[i][1] = random.randrange(1000)
    dot[i][2] = 0
dot.sort()
for i in range(input):
    x.append(dot[i][0])
    y.append(dot[i][1])
def distance(x, y):
    return float(math.sqrt(x * x + y * y))
def dac(left, right):
    global mindis, a, b
    len = right - left
    length = (right + left)
    cn.scatter(x, y, color='b', marker='.')
    if len <= 0:
        dis = 9999999999999
        return dis
    elif len == 1:
        dis = distance(dot[right][0]-dot[left][0], dot[right][1]-dot[left][1])
        cn.plot([dot[left][0], dot[right][0]], [dot[left][1], dot[right][1]], color='r')
        p.pause(0.1)
        cn.lines.pop()
        p.pause(0.1)
        if dis < distance(a[0]-b[0], a[1]-b[1]):
            a = [dot[right][0], dot[right][1]]
            b = [dot[left][0], dot[left][1]]
        return dis
    else:
        n = int(length / 2)
        midline = (dot[n][0] + dot[n+1][0]) / 2
        cn.plot([midline, midline], [0, 1000], color='b')
        p.pause(0.1)
        dis1 = dac(left, n)
        dis2 = dac(n+1, right)
    if dis1 <= dis2:
        md = dis1
    else:
        md = dis2
    if mindis > md:
        mindis = md
    for i in dot[left:n+1]:
        if abs(i[0] - midline) <= md:
            for j in dot[n+1:right+1]:
                if j[0] - midline <= md:
                    if i[1] - md <= j[1] <= i[1] + md:
                        dis3 = distance(i[0]-j[0], i[1]-j[1])
                        if mindis > dis3:
                            mindis = dis3
                        cn.plot([i[0], j[0]], [i[1], j[1]], color='r')
                        p.pause(0.1)
                        cn.lines.pop()
                        p.pause(0.1)
                        if dis3 < distance(a[0] - b[0], a[1] - b[1]):
                            a = [i[0], i[1]]
                            b = [j[0], j[1]]
    cn.lines.pop()
    return mindis
list = []
c = [1000, 1000]
d = [0, 0]
for i in range(input):
    for j in range(i+1, input):
        list.append(distance(dot[i][0]-dot[j][0], dot[i][1]-dot[j][1]))
        if distance(dot[i][0]-dot[j][0], dot[i][1]-dot[j][1]) < distance(c[0] - d[0], c[1] - d[1]):
            c = [dot[i][0], dot[i][1]]
            d = [dot[j][0], dot[j][1]]
list.sort()
print("检验:", list[0], c, d)
print("距离:", dac(0, input-1))
print("最近对:", a, b)
cn.plot([a[0], b[0]], [a[1], b[1]], c='b')
p.pause(5)

python函数众多,很多好用的函数都不懂。

虽然用了好几个小时,不过对python更熟悉了,也初步学会了python绘图。继续努力吧,明天能好好学逆向了。0.0