欧拉计划第18题 - 如何使用Python枚举树状结构中的所有可能路径?

6

我正在尝试以大西洋的方式学习Python,并卡在了欧拉计划#18上。

我在网络上找到的所有东西(除此之外还有更多的谷歌搜索)都是一些变体“虽然你可以暴力解决,但这里是一个更优雅的解决方案”...

我明白了,真的有很棒的解决方案,我期待着有一天'无环图'这个词会在我的脑海中呈现出更清晰的画面。但我需要先从基础开始看看状态,尝试使用暴力方法。所以问题来了:如何生成(枚举?)欧拉计划#18题中三角形的所有有效路径,并将它们存储在适当的Python数据结构中?(列表的列表是我最初的想法?)我不想要答案 - 我想知道如何暴力地遍历所有路径并将它们存储到数据结构中。
这是我得到的内容。我肯定是在错误地循环数据集。期望的行为应该是进行“深度优先(?)”而不仅仅是无效地循环每一行。我读了Norvig书的第3章,但无法翻译伪代码。尝试阅读AIMA python library的第三章,但它跨度太大。
triangle = [
    [75],
    [95, 64],
    [17, 47, 82],
    [18, 35, 87, 10],
    [20,  4, 82, 47, 65],
    [19,  1, 23, 75,  3, 34],
    [88,  2, 77, 73,  7, 63, 67],
    [99, 65,  4, 28,  6, 16, 70, 92],
    [41, 41, 26, 56, 83, 40, 80, 70, 33],
    [41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
    [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
    [70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
    [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
    [63, 66,  4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
    [04, 62, 98, 27, 23,  9, 70, 98, 73, 93, 38, 53, 60,  4, 23],
]


def expand_node(r, c):
    return [[r+1,c+0],[r+1,c+1]]

all_paths = []
my_path = []

for i in xrange(0, len(triangle)):
    for j in xrange(0, len(triangle[i])):
        print 'row ', i, ' and col ', j, ' value is ', triangle[i][j]
        ??my_path = somehow chain these together???
        if my_path not in all_paths
            all_paths.append(my_path)

最好避免使用外部库(如itertools)的答案。


3
问题在于暴力路径的数量为15!或1,307,674,368,000。您的计算机有多少内存? - Mark Tolonen
@MarkTolonen:问题信息显示只有16384条路线。不过,您为什么认为一个可行的解决方案必须记住所有路径呢? - martineau
1
@matineau,OP问道“如何暴力破解所有路径并将它们存储到数据结构中”。他也可以使用itertools逐个生成它们,那么他有多少时间?另外,我也以“快速”的方式解决了#18问题。 - Mark Tolonen
1
抱歉,我在考虑行的排列。它是2^14或16,384。 - Mark Tolonen
@euleruser:所有路径都通向终点。问题是找到那条通过数字产生最大总和的路径。 - martineau
显示剩余4条评论
1个回答

5

在这里使用递归更加简单:

def all_paths(r, c):
    current = triangle[r][c]
    if r < len(triangle) - 1:
        below_paths = all_paths(r+1, c) + all_paths(r+1, c+1)
        return [[current] + path for path in below_paths]
    else:
        return [[current]]

这里的想法是all_paths(r, c)返回从行r,列c开始的所有路径,通常通过递归地从其下面的两个节点获取所有路径,并将当前元素前置到所有路径中来实现。

如果我们处于最后一行,我们只需返回由单个元素组成的路径。

要获取从顶部开始的所有路径,请调用all_paths(0, 0)

然后可以轻松修改此函数,使其返回每个路径的总和而不是路径本身,并进行进一步修改以仅返回最大总和而不是所有总和。解决此问题的“正确方法”基本上就是该方法的记忆化版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接