数字三角形1
原题
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和(路径上的每一步只可沿左斜线向下或右斜线向下走)。
分析
逐行遍历每个数字,使用动态规划根据题意更新顶部的数字到当前所遍历的数字最大和,直到访问完底部的所有数字,最后得出顶部到底部最大的和。具体实现见下述源码。
源码
N = int(input())
mat_triangle = []
for _ in range(N):
m = map(int,input().split())
mat_triangle.append(list(m))
# row为行的索引(从0开始计)
for row in range(1,N):
# 走到当前最左边的数只能从上一行最左边的数沿左斜线向下过来
mat_triangle[row][0] += mat_triangle[row-1][0]
# 走到当前最右边的数只能从上一行最右边的数沿右斜线向下过来
mat_triangle[row][row] += mat_triangle[row-1][row-1]
for j in range(1,row):
# 当前位置从上一行沿左斜线向下和右斜线向下走过来
t = max( mat_triangle[row-1][j-1], mat_triangle[row-1][j])
mat_triangle[row][j] += t
print(max(mat_triangle[-1]))
测试示例
输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出
30
数字三角形2
原题
在数字三角形1的基础上修改走到另一步的条件:路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入输出与数字三角形1一致。
原题链接:https://www.lanqiao.cn/problems/505/learning/
分析
本题基本解题思路和数字三角形1差不多,关键在于最后形成的“路径”的两个方向的走的次数相差不超过1,这要利用我们很容易看出的两个“条件”:①三角形的第i行(i=1, 2, 3, ...)有i个数字;②起点是最顶部的第一个点,它位于三角形的最中间。
利用以上条件,不难发现,最终得到的最大和一定位于输入的数字三角形的最后一行的中间的位置。解题方法在前期的动态规划求每个数字到最顶部的数字的”路径最大和“相同,只是最终的最大和的所在的位置有所不同。
有两种情况:①最后一行有奇数个数字,此时按照题意最终只能走到最后一行数字中处于中间位置的一个数字(最后向左走和向右走的次数相差为0);②最后一行有偶数个数字,此时按照题意最终只能走到最后一行数字中处于中间位置的两个数字(最后向左走和向右走的次数相差分别为1、-1)。
按照题意从三角形的顶部走到底部一定会走到底部的中间位置,这是本题的一个关键点、也是易错点。本人就犯过这样的一个错误:记录每次走的方向的次数,保证每走完一步后两个方向走的次数相差不超过1。这是本人理解错题意了,其实只要保证走到最后一步时两个方向走的次数相差不超过1即可,根据数字三角形的特性,不必记录每次走的方向的次数。
源码
N = int(input())
mat_triangle = []
for _ in range(N):
m = map(int,input().split())
mat_triangle.append(list(m))
# row为行的索引(从0开始计)
for row in range(1,N):
# 走到当前最左边的数只能从上一行最左边的数沿左斜线向下过来
mat_triangle[row][0] += mat_triangle[row-1][0]
# 走到当前最右边的数只能从上一行最右边的数沿右斜线向下过来
mat_triangle[row][row] += mat_triangle[row-1][row-1]
for j in range(1,row):
# 当前位置从上一行沿左斜线向下和右斜线向下走过来
t = max( mat_triangle[row-1][j-1], mat_triangle[row-1][j])
mat_triangle[row][j] += t
if N%2 == 0:
loc = N//2
res = max(mat_triangle[-1][loc-1:loc+1])
else:
res = mat_triangle[-1][N//2]
print(res)
测试示例
输入1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出1
27输入2
6
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
9 2 1 5 3 7
输出2
32
上一篇:蓝桥杯备战日志(Python)10-最短路-(图的遍历)