给出了一个字典,字典中的点数很少,它们之间的距离为键-点的名称和值-距离,即
points_dict = {"a": 18, "b": 7, "c": 15, "d": 22, "e": 33, "f": 5}
问题是要找到f.e. 6 条最短路径,以便与该字典形成 3 个不同的点,因此 6 条最低总和为 3 个与依次指定dict值。
我尝试通过以下方式进行操作-将距离归纳到一个列表中,然后将其排序为:
example_list = [5, 7, 15, 18, 22, 33]
然后只获得前6种组合,所以:
- 5 + 7 + 15
- 5 + 7 + 18
- 5 + 7 + 22
- 5 + 7 + 33
- 7 + 15 + 18
以此类推...
但是正如您所看到的,这是不对的,因为4. 5+7+33 = 45
而5. 7+15+18 = 40
,所以它应该在它之前,作为最小的和,所以是“最短”的距离。我想不出任何算法和解决方案来解决这个问题。有什么技巧可以做到吗?
谢谢。
答案 0 :(得分:0)
您可以使用itertools中的powerset recipes,将其与collection.defaultdict结合使用,并且仅使用具有3个元素元组的元素。但是,这会产生过多的数据-如果您有巨大的字典,它不是最佳选择:
from itertools import combinations, chain
from collections import defaultdict
# https://docs.python.org/3/library/itertools.html#recipes
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
# you can hardcode your 3-tuples here as well and eliminate lots of data and filtering
# return combinations(s, 3)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
points_dict = {"a": 18, "b": 7, "c": 15, "d": 22, "e": 33, "f": 5}
d = defaultdict(list)
for s in powerset(points_dict.values()):
if len(s) == 3:
d[sum(s)].append(s)
sor = sorted(d)
for s in sor:
print(s, d[s])
输出:
27 [(7, 15, 5)]
30 [(18, 7, 5)]
34 [(7, 22, 5)]
38 [(18, 15, 5)]
40 [(18, 7, 15)]
42 [(15, 22, 5)]
44 [(7, 15, 22)]
45 [(18, 22, 5), (7, 33, 5)]
47 [(18, 7, 22)]
53 [(15, 33, 5)]
55 [(18, 15, 22), (7, 15, 33)]
56 [(18, 33, 5)]
58 [(18, 7, 33)]
60 [(22, 33, 5)]
62 [(7, 22, 33)]
66 [(18, 15, 33)]
70 [(15, 22, 33)]
73 [(18, 22, 33)]
答案 1 :(得分:0)
一旦有了example_list = [5, 7, 15, 18, 22, 33]
,您就可以使用此衬纸来获取按3个元素的总和排序的组合列表:
from itertools import combinations
sorted(list(combinations(example_list, 3)),key=sum)
#=> [(5, 7, 15), (5, 7, 18), (5, 7, 22), (5, 15, 18), (7, 15, 18), (5, 15, 22), (7, 15, 22), (5, 7, 33), (5, 18, 22), (7, 18, 22), (5, 15, 33), (7, 15, 33), (15, 18, 22), (5, 18, 33), (7, 18, 33), (5, 22, 33), (7, 22, 33), (15, 18, 33), (15, 22, 33), (18, 22, 33)]
然后选择前六个。
如果您还想跟踪原始密钥:
tmp_list = [[k, v] for k, v in points_dict.items()]
sorted(list(combinations(tmp_list, 3)), key = lambda x: sum(i[1] for i in x) )[0:6]
#=> [(['c', 15], ['b', 7], ['f', 5]), (['a', 18], ['b', 7], ['f', 5]), (['b', 7], ['d', 22], ['f', 5]), (['a', 18], ['c', 15], ['f', 5]), (['a', 18], ['c', 15], ['b', 7]), (['c', 15], ['d', 22], ['f', 5])]
答案 2 :(得分:0)
您可以使用itertools中的powerset收据,将其与colleciton.defaultdict结合使用,并且仅使用具有3个元素元组的收据:
from itertools import combinations, chain
# https://docs.python.org/2/library/itertools.html#recipes
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
points_dict = {"a": 18, "b": 7, "c": 15, "d": 22, "e": 33, "f": 5}
from collections import defaultdict
d = defaultdict(list)
for s in powerset(points_dict.values()):
if len(s) == 3:
d[sum(s)].append(s)
sor = sorted(d)
for s in sor:
print(s, d[s])
输出:
27 [(7, 15, 5)]
30 [(18, 7, 5)]
34 [(7, 22, 5)]
38 [(18, 15, 5)]
40 [(18, 7, 15)]
42 [(15, 22, 5)]
44 [(7, 15, 22)]
45 [(18, 22, 5), (7, 33, 5)]
47 [(18, 7, 22)]
53 [(15, 33, 5)]
55 [(18, 15, 22), (7, 15, 33)]
56 [(18, 33, 5)]
58 [(18, 7, 33)]
60 [(22, 33, 5)]
62 [(7, 22, 33)]
66 [(18, 15, 33)]
70 [(15, 22, 33)]
73 [(18, 22, 33)]