[POJ1163 IN PYTHON] P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles

题目描述

观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

         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(i1,j1),L(i1,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值