分治法求解最近对问题

老师好,我是刁同学。

  1. 以先x坐标增序,再y坐标增序对点集S中的点排序
  2. S点集被垂直线L大约划分成两个子集L是经过x坐标为S[n//2]的垂线
  3. 递归以上两步,两子集SL和SR的最小间距可分别计算出来lengthl和lengthr
  4. 组合步骤,把在SL中的点与SR中的点之间最小间距length算出来
import numpy as np
import matplotlib.pyplot as plt
def distance(p,i,j):
    h=pow((pow((p[i][0]-p[j][0]),2) +pow((p[i][1] - p[j][1]),2)),1.0/2)
    return h
def point():
    n=int(input("点集大小:"))
    p=[[0,0]]*n
    x=[]
    y=[]
    for i in range (0,n):
        p[i]=[float(input("x=")),float(input("y="))]
        x.append(p[i][0])
        y.append(p[i][1])
    return p,x,y
def cp(pair):
    global min_i,min_j
    min_i =[None,None]
    min_j = [None, None]
    if len(pair)<=3:
        length=1000
        for i in range(0,len(pair)):
            for j in range(i+1,len(pair)):
                if length>=distance(pair,i,j):
                    length=distance(pair,i,j)
                    min_i=pair[i]
                    min_j=pair[j]
    else:
        mid=len(pair)//2
        x0=pair[mid][0]
        lengthl=cp(pair[0:mid+1])
        MINI=min_i
        MINJ=min_j
        lengthr=cp(pair[mid+1:])
        if lengthl<lengthr:
            min_i=MINI
            min_j=MINJ
        length=min(lengthl,lengthr)
        k=0
        T=[]
        for i in range(0,len(pair)):
            if (abs(p[i][0]-x0)<=length):
                T.append(p[i])
                k+=1
        length_=2*length
        for i in range(0,k-1):
            for j in range(i+1,min(i+7,k)):
                if distance(T,i,j)<length_:
                    length_=distance(T,i,j)
                    min_i_=T[i]
                    min_j_=T[j]
                if length>length_:
                    min_i=min_i_
                    min_j=min_j_
        length=min(length,length_)
    return length

x=[]
y=[]
p=[[]]
#p=[]
# for _ in range (0,10):
#     x.append(np.random.randint(-20,20))
#     y.append(np.random.randint(-20,20))
#     p.append([x[_],y[_]])
p,x,y=point()
p.sort(key=lambda m:[m[0],m[1]])
print(p)
print(cp(p))
print(min_i)
print(min_j)
plt.figure(figsize=(20,8),dpi=80)
plt.scatter(x,y,s=20,c='b',marker='*')
plt.plot([min_i[0],min_j[0]],[min_i[1],min_j[1]],c='r')
plt.show()

代码的运行结果
***------输入------*** 加载中

点集大小:10
x=7.89 y=6.54
x=3.2 y=9.8
x=7.9 y=3.5
x=-1.4 y=-5.7
x=12.9 y=2
x=2.5 y=4.8
x=-2.3 y=4.4
x=0 y=0.8
x=2.82 y=3.14
x=5.35 y=7

------输出------ 加载中

点集:[[-2.3, 4.4], [-1.4, -5.7], [0.0, 0.8], [2.5, 4.8], [2.82, 3.14], [3.2, 9.8], [5.35, 7.0], [7.89, 6.54], [7.9, 3.5], [12.9, 2.0]]
最近距:1.6905620367203325
PonitA:[2.5, 4.8]
PointB:[2.82, 3.14]

在这里插入图片描述
以下是生成50个点时的效果图
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值