最近點對問題python解法
阿新 • • 發佈:2019-01-05
開始複習之前學過的內容,與大家分享下
目標:
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)