题目描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大,=30
输入格式
第一个行包含 R(1<= R<=1000) ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。
输出格式
单独的一行,包含那个可能得到的最大的和。
输入输出样例
输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出
30
思路
使用动态规划并部署记忆化查询减少时间开销.
对于每一层的每一个节点进行规划.
状态转移方程:
L
(
i
,
j
)
=
m
a
x
(
L
(
i
−
1
,
j
−
1
)
,
L
(
i
−
1
,
j
)
)
+
v
a
l
u
e
(
i
,
j
)
L(i,j)=max(L(i-1,j-1),L(i-1,j))+value(i,j)
L(i,j)=max(L(i−1,j−1),L(i−1,j))+value(i,j)
之前没考虑到这种思路.知道要用DP但是没有 考虑到对每个结点部署DP,还是停留在每一层部署DP上.当然对这一题要求只能从左右节点的就不行了.
初态:
L
(
0
,
0
)
=
v
a
l
u
e
(
0
,
0
)
L(0,0)=value(0,0)
L(0,0)=value(0,0)
最后检查最后一行的每个节点的
L
L
L,输出最大值.
实现
注意到对于边界值Node[i][0]
和Node[i][i]
,在比较时提取不到上一行的边界节点会报错.
所以对每一行的
L
(
i
,
,
j
)
L(i,,j)
L(i,,j),设计成如下形式:
[0, [-1, 1, -1], [0, 2, 3, 0], [0, 3, 5, 6, 0]]
- 第一列的0是占位符.
- 除了[1]之外,其余行的L数据在首尾填充0,在边界进行判断时不会发生错误.
- [1]使用-1是因为避免[0][0]=0的情况.(好像也没差?)
源码
def triangle():
a=int(input())
data=[]
for _ in range(int(a)):
data.append(input().split())
for i in range(len(data[-1])):
data[-1][i]=int(data[-1][i])
#data:[[level0],[level1],...]
solution=[0,[-1,data[0][0],-1]]#[1] is the top
#print(data)
if a==1:
print(data[0][0])
return
else:
for i in range(2,a+1):#Non-0-style
rowtemp=[0]#Reset
for j in range(1,i+1):
rowtemp.append(max(solution[i-1][j-1],solution[i-1][j])+data[i-1][j-1])
rowtemp.append(0)
solution.append(rowtemp)
print(solution)
print(max(solution[-1]))
return
if __name__=="__main__":
triangle()
洛谷已确认AC.
参考
https://blog.csdn.net/bear_huangzhen/article/details/45967189
https://blog.csdn.net/Eternally831143/article/details/79346557