Acwing1015. 摘花生 python实现

1. 题目描述#

给定一个矩阵,矩阵中元素的值表示花生的个数
从左上角走到右下角,只能向右走或者向下走,问能采到的花生最大值是多少

典型的数字三角形模型,求最大路径和

2. 题目思路#

  1. 从集合角度考虑DP问题
  • 状态表示f[i,j]

    • 集合:从左上角点(1,1)(ij)的所有路线
    • 属性:最大值

    理解:集合表示f[i,j]涵盖的范围,属性表示f[i,j]的值,代表的是最大值

    因此题目的答案就是f[n,m]

  • 状态计算

    • 状态计算一般考虑的是走到该位置的最后一步是从哪里走的

    • 根据题意可知,走到(i,j)的最后一步,要不就是从上面(i1,j),要不就是从下面(i,j1)走过来的

    • 要求f[i,j]的最大值,可以通过求上一步的最大值+从上一步到(i,j)的值【这样使得求解范围变小】,那上一步的最大值怎么求?其实就是状态的定义f[i1,j]f[i,j1],有两个“上一步”,那就看哪一步的结果更大,选哪一步了

    • 因此,状态的计算可以归纳为:

      f[i,j]=max(f[i1,j]+g[i,j],f[i,j1]+g[i,j])

      简化写就是 f[i,j]=max(f[i1,j],f[i,j1])+g[i,j]

  1. 剩下就是考虑初始化和遍历顺序的问题了。

    • 由于是从1开始计数的,因此可以利用初始化而不用去特判边界。我是根据边界应为f[1,1]=g[1,1],而f[1,1]=max(f[0,1],f[1,0])+g[1,1] 可知,应将f初始化为0

    • 从状态计算可以得知,要知道前面的结果才能推出后面的,因此应从上往下从左往右去遍历

3. 代码实现#

输入:

T组数据

行数R和列数C

R行C列花生个数

注意是从1开始计数的

输出:

花生数最大值

python3实现:

朴素做法,时间复杂度O(n2)

Copy
t = int(input()) while t: # 读取数据 n, m = tuple(map(int, input().split(" "))) g = [0 for _ in range(n)] dp = [[0 for _ in range(m + 1)]for _ in range(n + 1)] for i in range(n):# 一行一行读 g[i] = list(map(int, input().split(" "))) # dp for i in range(1, n+1): for j in range(1, m + 1): dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + g[i - 1][j - 1] # 是因为g是从0开始存的 print(dp[n][m]) t -= 1

4. 扩展:如果要求的是最小值呢?#

如果还是dp[i][j]=max(dp[i1][j],dp[i][j1])+g[i1][j1],那边界第一行和第一列会受到第0行和第0列的影响(因为dp的值都是0),因此对于边界需要特判。
特判的方法有两种:

  1. 先把第一行和第一列的dp值处理好,然后i和j都从2到n遍历
  2. 当i不为1才可以执行dp[i-1][j]+g[i][j];当j不为1才可以执行dp[i][j-1]+g[i][j],此时只需特判左上角(既是第一行又是第一列)
    这里给出第二种的写法
Copy
for i in range(1,n+1): for j in range(1,n+1): if i == 1 and j == 1: dp[i][j] = g[i-1][j-1] else: dp[i][j] = 0x3f3f3f3f if i > 1: dp[i][j] = min(dp[i][j], dp[i-1][j] + g[i-1][j-1]) if j > 1: dp[i][j] = min(dp[i][j], dp[i][j-1] + g[i-1][j-1])

1018题的最低通行费就是这么解的。

posted @   要兵长还是里维  阅读(126)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示
CONTENTS