最强的一点点蛮力

时间:2017-11-03 06:52:54

标签: python

我不知道我的代码有什么问题。我生成100个随机点,我想找到最接近的一对点,但结果是错误的。

#Closest pair
from math import sqrt
from random import randint

arr1=[]

dist=0
p1=[]
p2=[]
min1=1000
for i in range(0, 100):
    arr1.append([randint(0,100),randint(0,100)])

print(arr1)
print("\n")

def dist(a,b):
    x=pow((a[0]-b[0]),2)
    y=pow((a[1]-b[1]),2)
    return sqrt(x+y)

for i in range(0, len(arr1)):
    for j in range(i+1, len(arr1)):
    dis=dist(arr1[i],arr1[j])
    if(dis<min1):
        min1=dis
        p1=arr1[i]
        p2=arr1[j+1]

print(p1,"",p2,min1)
#print (sorted(arr1))

4 个答案:

答案 0 :(得分:2)

你认为(1,5)和(5,1)是正确的相同点。然而,当你从i + 1循环到100你添加arr1 [j + 1]我想这是错误的考虑当j = 100并且你得到最接近的点然后你将最终得到arr1 [101]

答案 1 :(得分:1)

正如İhsanCemilÇiçek所提到的,您的代码的主要问题是您有p2=arr1[j+1],应该是p2=arr1[j]

但是,您可以采取一些措施来提高此代码的效率。

没有必要为每个距离测试取平方根。对于非负d1d2,如果sqrt(d1) < sqrt(d2)然后d1 < d2,那么我们只需测试平方距离,我们只需要进行一次昂贵的平方根计算当我们找到最小值时。

Python具有高效的min功能,因此无需手动找到最小值。通常,min会对您传递的值进行简单比较,但您也可以为其提供一个用于进行比较的键函数。

您可以使用标准combinations模块中的itertools函数,通过单个循环从点列表中生成项目对。这不会节省太多时间,但它比双循环更清晰。

此外,在开发生成随机值的代码时,最好为随机数生成器提供种子值。这样可以更容易地进行测试。调试代码,因为它使结果可重现。

在下面的代码中,我增加了坐标的范围,因为坐标在0到100范围内的100个点很有可能生成重复点。如果您不想要重复的点,您可能希望使用集合而不是列表。

from math import sqrt
from random import seed, randint
from itertools import combinations

seed(17)

high = 1000
numpoints = 100

points = [(randint(0, high), randint(0, high)) for _ in range(numpoints)]
points.sort()
print(points, '\n')

def dist(t):
    a, b = t
    x = a[0] - b[0]
    y = a[1] - b[1]
    return x*x + y*y

t = min(combinations(points, 2), key=dist)
a, b = t
print('{} {}: {}'.format(a, b, sqrt(dist(t))))

<强>输出

[(9, 51), (18, 443), (19, 478), (21, 635), (27, 254), (50, 165), (52, 918), (55, 746), (70, 316), (95, 707), (112, 939), (113, 929), (126, 903), (132, 256), (143, 832), (145, 698), (154, 692), (187, 200), (197, 765), (201, 154), (203, 317), (217, 51), (244, 119), (257, 983), (258, 880), (264, 76), (273, 65), (279, 343), (296, 178), (325, 655), (326, 174), (338, 552), (340, 96), (363, 51), (368, 59), (381, 585), (383, 593), (393, 834), (411, 140), (412, 496), (419, 83), (485, 648), (491, 76), (513, 821), (519, 962), (534, 424), (539, 980), (545, 572), (549, 312), (555, 87), (564, 63), (566, 923), (568, 545), (570, 218), (577, 537), (592, 801), (618, 848), (655, 614), (673, 413), (674, 314), (677, 284), (702, 141), (702, 215), (721, 553), (732, 654), (749, 974), (762, 279), (764, 429), (766, 732), (770, 756), (771, 356), (784, 722), (789, 319), (792, 5), (805, 282), (810, 896), (821, 978), (824, 911), (826, 310), (830, 323), (831, 418), (832, 518), (836, 400), (859, 256), (862, 996), (866, 700), (879, 485), (888, 415), (903, 722), (930, 588), (931, 496), (938, 356), (942, 323), (942, 344), (948, 429), (967, 741), (980, 254), (982, 488), (982, 604), (983, 374)] 

(381, 585) (383, 593): 8.246211251235321

答案 2 :(得分:0)

它只适用于第一点,对于列表中的所有其他点,您只是检查(i + 1到n)中的剩余点而不是所有点。(最近点也可能在0到i之间)

答案 3 :(得分:0)

你应该在for循环中使用enumerate,现在你正在检查i对与数组中出现的所有对,那么他之前的对呢? 另外,你需要保存符合距离条件的第一对和第二对作为i和j对,为什么配对[j + 1]?

试试这个,我认为它应该有效:

from math import sqrt
from random import randint
arr1=[]

dist=0
p1=[]
p2=[]
min1=1000
for i in range(0, 100):
  arr1.append([randint(0,100),randint(0,100)])

print(arr1)
print("\n")


def dist(a,b):
  x=pow((a[0]-b[0]),2)
  y=pow((a[1]-b[1]),2)
  return sqrt(x+y)


 for i,x in enumerate (arr1):
   for j,y in enumerate (arr1):
    if (x != y):
    dis=dist(arr1[i],arr1[j])
    if(dis<min1):
      min1=dis
      p1=arr1[i]
      p2=arr1[j]


print(p1,"",p2,min1)
print (sorted(arr1))