蓝桥云课——跳跃 Python(动态规划)

 题目地址:跳跃 

        此题是一道比较经典又带有一定难度的动态规划题目,且听我慢慢道来(虽然不一定能讲明白:( )

先输入数据:

n, m = map(int, input().split())
score = []
for i in range(n):
    score.append(list(map(int, input().split())))

        动态规划第一步,动态规划必要dp数组,我们先确定dp数组的含义,此题目要求求出权的最大值,那我们dp数组的含义便是所含最大权和,那么dp[n-1][m-1]便是我们要找的答案。

        动态规划第二部,也是最难的一步,便是确认dp数组,一旦确认的dp数组,代码和思路必然会好写很多,对于这道题,我们可以采用自顶向下的备忘录递归解法,在此,我们采用自底向上的动态规划解法。对于一般动态规划问题,我们经常采用先假设一个中间常量,然后思考如何才能到达这个中间项,以此题为例,假设我们在求解过程中到达了一个点dp[i][j],我们如何才能到达这个点呢?以下图我们可以知道,黑色为假设点,其周围绿色的是可以到达假设点的所有点,而我们的目的就是求出权的最大值,所以dp方程的大体思路我们就知道了,dp[i][j] = max(dp[i][j],???),对于???来说,我们知道要求最大值,但是如何取到呢?我们可以采用设置jump数组来表示点的移动,所以dp方程为:dp[i][j] = max(dp[x][y], dp[i][j])

  设立jump数组:

jump = [[0, -1], [0, -2], [0, -3], [-1, 0], [-2, 0], [-3, 0], [-1, -1], [-1, -2], [-2, -1]]  # 表示移动方向

用for循环来实现点的移动:

        

for dx, dy in jump:
    x = i + dx
    y = j + dy

        动态规划第三步,初始化数据,因为dp数组中我们存在max()函数,所以我们先把dp数组值取最小,对于dp[0][0]来说,他就是初始点,没有任何一个点能从别的点到达此点,所以其值为初始值。

初始化:

dp = [[-99999] * m for _ in range(n)]
dp[0][0] = score[0][0]

注意设立二维数组时不能以以下语句:

dp = [[-99999] * n] * m

这样设置会导致你变化其中一行时,所有行都会变化,因为他们的地址是一样的。

完整代码:

n, m = map(int, input().split())
score = []
jump = [[0, -1], [0, -2], [0, -3], [-1, 0], [-2, 0], [-3, 0], [-1, -1], [-1, -2], [-2, -1]]  # 表示移动步数
for i in range(n):
    score.append(list(map(int, input().split())))
dp = [[-99999] * m for _ in range(n)]

dp[0][0] = score[0][0]
for i in range(n):
    for j in range(m):
        if i == j == 0:  # 起始点,已经不能再上下移动了
            continue
        for dx, dy in jump:  # 开始索引最大权值
            x = i + dx  # i不能变,因为i还要参与循环
            y = j + dy
            if x >= 0 and x < n and y >= 0 and y < m:  # 跳跃过程中不能越界
                dp[i][j] = max(dp[x][y], dp[i][j])  # dp方程
        dp[i][j] += score[i][j]  # 将最大的权值加上
        
print(dp[n - 1][m - 1])

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值