1. 程式人生 > >最近點對問題python解法

最近點對問題python解法

開始複習之前學過的內容,與大家分享下

目標:

INPUT: 平面上的 n 個點

OUTPUT: 歐式距離最近的點對

最原始想法:遍歷所有點的集合,具有o(n^2)的時間複雜度

可以使用分治思想進行演算法優化.

首先將所有點按照X軸排序(Y軸也可以),之後進行分割為左一半元素,右一半元素,最後左右分別求最近點,最後進行合併,找到左面和右面的點集合裡面最小的.

這裡的一個trick是找到左右最小距離後,只需要在中間位置使用最小距離約束,如下,左右最小距離是12,只需要考慮中線(-12,12)以內的值就可以,最後遞迴呼叫即可


import math
import random
a=[(500*random.random(), 500*random.random()) for i in range(0,300)]
a.sort()
par=[]
mi=float("inf")
def eudis(x,y):
    global par
    h=math.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2)
    if h<mi:
        par=[]
        par.append(x)
        par.append(y)
    return h
        
def combine(l1,l2,alpha):
    x=float("inf")
    mini=l1[-1][0]-alpha
    maxi=l1[-1][0]+alpha
    for i in l1:
        if (mini<i[0]<maxi):
            for j in l2:
                if ((mini<j[0]<maxi)and abs(i[1]-j[1])<alpha):
                    x=min(x,eudis(i,j))
    return x
    
def divide(a):
    global mi
    if (len(a)==2):
        return eudis(a[0],a[1])
    if (len(a)<2):
        return float("inf")
    else:
        i=int(len(a)/2)
        left = a[0:i]
        right = a[i:]
        s1=divide(left)
        s2=divide(right)
        s3=combine(left,right,mi)
        s=min(s1,s2,s3)
        mi=min(s,mi)
        return mi
jieguo=divide(a)