给定一个由n行数字组成的数字三角型,如图所示。设计一个算法,计算从三角形的顶至底的一条路径,使该路径经过的数字总和最大。路径上的每一步都只能往左下或右下走,给出这个最大和。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
这个问题来源于POJ1163。对于这种问题,我们可以有正向和反向两种思考方式。正向思考这个问题,dp[i][j]表示从第一行第一列到第i行第j列最大的数字总和;反向思考这个问题,dp[i][j]表示从第i行第j列到最后一行最大的数字总和。反向思考的代码要简洁一些,在POJ上这两份代码所用时间都是32MS。当然我们还可以对空间再进行优化,这里就不再细说了。
#coding:utf-8
import sys
if __name__ == '__main__':
n = input()
a = []
for i in range(n):
b = sys.stdin.readline().strip().split(' ')
b = map(int, b)
a.append(b)
dp = [[0] * n for i in range(n)]
dp[0][0] = a[0][0] #初始化状态
for i in range(1, n):
for j in range(0, i + 1):
if j != 0:
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + a[i][j]) #更新状态
if j != i:
dp[i][j] = max(dp[i][j], dp[i - 1][j] + a[i][j]) #更新状态
c = 0
for i in range(0, n):
if c < dp[n - 1][i]:
c = dp[n - 1][i]
print c
从最底层开始往上走:
#coding:utf-8
import sys
if __name__ == '__main__':
n = input()
a = []
for i in range(n):
b = sys.stdin.readline().strip().split(' ')
b = map(int, b)
a.append(b)
dp = [[0] * n for i in range(n)]
for i in range(0, n):
dp[n - 1][i] = a[n - 1][i]
for i in range(1, n):
for j in range(0, n - i):
dp[n - 1 - i][j] = max(dp[n - i][j] + a[n - 1 - i][j], dp[n - i][j + 1] + a[n - 1 - i][j])
print dp[0][0]