【问题标题】:Project Euler Problem 18: What mistake did I make in my code?Project Euler 问题 18:我在代码中犯了什么错误?
【发布时间】:2019-10-07 05:15:46
【问题描述】:

https://projecteuler.net/problem=18

给定一个整数三角形,问题是找到从上到下的最大路径和(路径中的所有数字必须相邻)。

我有一个算法的想法:从最顶端开始,计算左右路径之和(一直向下,向右一直向下),如果左侧和更大,则跳转到左边相邻的数字,如果右边的和更大,则跳到右边相邻的数字,从当前数字开始重复算法,依此类推,直到到达最后一行。

triangle = ['75', '9564', '174782', '18358710', '2004824765', '190123750334', '88027773076367', '9965042806167092', '414126568340807033', '41487233473237169429', '5371446525439152975114', '701133287773177839681757', '91715238171491435850272948', '6366046889536730731669874031', '046298272309709873933853600423']

maximumPath = [75]
maxSum = 75 #Start it with the starting element of the triangle.

def triNum(row, index): #Returns the number at given row, number in row
    return(int(triangle[row][2*index:2*(index+1)])) #Nota bene: returns an integer.

def options(row, index): #Rows start at 0, index starts at 0
    return(triNum(row+1, index), triNum(row+1, index+1))

def criticalPathSum(startRow, startIndex, direction):
    critPath = []
    if direction == 'left':
        directionNum = 0
    else:
        directionNum = 1
    sum = triNum(startRow, startIndex) #Starting sum of left and right paths is just the number at the start of both paths.
    for i in range(startRow + 1, len(triangle)):
        startIndex += directionNum
        sum += triNum(i, startIndex)
        critPath.append(triNum(i, startIndex))
        #print(triNum(i, startIndex + directionNum))
    return(sum, critPath)

pathIndex = 0
for row in range(0, len(triangle)-1):
    print('These are my options: ' + str(options(row, pathIndex)))
    print('Left Sum: ' + str(criticalPathSum(row, pathIndex, 'left')) + ', ' + 'Right Sum: ' + str(criticalPathSum(row, pathIndex, 'right')))
    if criticalPathSum(row, pathIndex, 'left') > criticalPathSum(row, pathIndex, 'right'):
        maximumPath.append(triNum(row + 1, pathIndex))
        print('Left. ' + str(triNum(row + 1, pathIndex)))
    else:
        print('Right. ' + str(triNum(row + 1, pathIndex + 1)))
        pathIndex += 1
        maximumPath.append(triNum(row + 1, pathIndex))
    maxSum += triNum(row + 1, pathIndex)
    print('_______________________________')
    print('\n')
print(maximumPath)
print(maxSum)

答案是 1067,但我得到 883。这是最大路径,根据算法:

[75, 95, 17, 35, 82, 75, 7, 16, 80, 37, 91, 17, 91, 67, 98].

【问题讨论】:

  • 答案不是 1067。
  • 从你的描述来看,我猜你的代码不一定有问题,但你的算法有问题。例如,试试三角形[20], [15, 18], [20, 50, 13]。根据您的描述,听起来您的算法会产生结果 85,而应该很容易看出答案应该是 88。
  • 那么你需要创建从上到下的所有路径,即创建一个树结构,其中每个节点都是前一个节点的相邻元素。它会创建一个二叉树,通过它解析你会得到最大的结果,这是实际结果1074 = 75+64+82+87+82+75+73+28+83+32+93+73+58+78+91
  • 如果您需要代码或逻辑方面的帮助go through this

标签: python algorithm


【解决方案1】:

你的算法是错误的:在三角形中

   1
  1 4
 1 4 1
9 1 4 1

9(总是向左走)太诱惑了,看不到最佳的1+4+4+4 = 13 路线。

【讨论】:

  • 目标是找到最大的结果,所以通过下一层相邻元素的最大值并不能保证最大的结果,所以需要遍历所有节点,使用二叉树创建
【解决方案2】:

这是测试数据旨在击败的众多错误算法之一。您选择了一种所谓的“贪心”算法,该算法对任何一步都取最大值,而不考虑问题的长期特征。

相反,您需要从三角形底部向上工作。在每个接合点,记下两条路径中的哪一条给出了三角形底部的最大总和,并将其记录为该节点的最佳结果。当您到达顶点时,您将得到所需的答案,即下方两个元素中较大的一个。

例如,给定三角形

   1
  2 1
 2 1 9
1 2 1 9

您的算法将是贪婪的并采用路径 1-2-2-2;第二行中1 的较低选择会从短视逻辑中切断该分支。

相反,您需要从底部开始构建总计,在每个节点处取两条路径中的最佳路径:

   20
  6 19
 4 3 18
1 2 1 9

如果这还不够清楚...... 最下面一行没有其他选择;每个值都是它自己到达终点的最佳路径。对于上面的行,让我们从右到左,考虑每个值及其两个“孩子”:

 2 1 9
1 2 1 9

2 有以下两个值,12。显然,2 更好,所以从那里开始的最佳路径是 2+2 = 4。 1 同样在下面有21;同样,更好的路径是 1+2,给出 3。 919 的孩子;我们选择 9+9=18。这些行现在显示为

   1
  2 1
 4 3 18
1 2 1 9

现在我们向上移动一排,将2 1 的两个选项合并在一起。 2431318。再次在每种情况下取​​较高的值并添加节点值,我们得到 2+4 = 6 和 1+18 = 19:

   1
  6 19
 4 3 18
1 2 1 9

最后,顶部节点选择较大的值 19,沿路径 1-1-9-9 总共有 20 个。

知道了吗?

【讨论】:

    猜你喜欢
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多