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].
答案 0 :(得分:2)
您的算法是错误的:像这样的三角形
1
1 4
1 4 1
9 1 4 1
9
太诱惑(总是向左走),看不到最佳的1+4+4+4
= 13
路线。
答案 1 :(得分:1)
这是测试数据旨在克服的许多错误算法之一。您选择了一种所谓的“贪婪”算法,该算法在不考虑问题的长期特征的情况下,在任何单个步骤中都采用最大值。
相反,您需要从三角形的底部向上进行操作。在每个接合点,请注意两条路径中的哪条路径将最大和求和到三角形的底部,并记录为该节点的最佳结果。当您到达顶点时,您将得到所需的答案,因为其下面的两个元素中的较大者。
例如,给定三角形
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
在下面有两个值,1
和2
。显然,2
更好,因此从那里的最佳路径是2 + 2 = 4。
1同样在下面有一个2
和1
;同样,更好的路径是1 + 2,得出3。
9
有1
和9
的子级;我们选择9 + 9 = 18。这些行现在显示为
1
2 1
4 3 18
1 2 1 9
现在,我们上移一行,在那里2 1
的两个选择是强制的。
2
具有4
和3
; 1
具有3
和18
。再次在每种情况下取较高的值并加上节点值,我们得到2 + 4 = 6和1 + 18 = 19:
1
6 19
4 3 18
1 2 1 9
最后,顶部节点选择较大的值19,沿路径1-1-9-9总共为20。
知道了吗?