蓝桥杯备战日志(Python)13-跳跃-(遍历、动态规划)
原创
©著作权归作者所有:来自51CTO博客作者Helloyouth的原创作品,请联系作者获取转载授权,否则将追究法律责任
原题
小蓝在一个 行 列的方格图中玩一个游戏。
开始时,小蓝站在方格图的左上角,即第 行第 列。
小蓝可以在方格图上走动,走动时,如果当前在第 行第 列,他不能走到行号比 小的行,也不能走到列号比 小的列。同时,他一步走的直线距离不超过 。
例如,如果当前小蓝在第 行第 列,他下一步可以走到第 行第 列、第 行第 列、第 行第 列、第 行第 列、第 行第 列、第 行第 列、第 行第 列、第 行第 列、第 行第 列之一。
小蓝最终要走到第 行第 列。
在图中,有的位置有奖励,走上去即可获得,有的位置有惩罚,走上去就要接受惩罚。奖励和惩罚最终抽象成一个权值,奖励为正,惩罚为负。
小蓝希望,从第 行第 列走到第 行第 列后,总的权值和最大。请问最大是多少?
分析
本题考查动态规划算法,这里求n*m的数字矩阵中从第一个数按照题意的走法”走到“最后一个数,所经过的数字的最大和为多少?
首先,我们先理清楚”走法“,以下图的6行8列的数字矩阵为例,当前走到35的位置,则下一步走的位置在图中蓝色线经过的数字的位置,题意中的3步内是指向右走或向下走的距离不超过3(任意上下左右相邻的两个数距离为1)。
所谓动态规划,常常需要根据前面步骤引起的状态变化更新后面的状态。这里我们需要逐一访问矩阵中每个数字,更新第一个数字到当前遍历的数字经过的路的最大权值,即所经过的数字的最大和。
解题的关键点在于:访问到当前数字,它可以从哪些数字走过来,从这些数字中的哪一个走过来会使和最大。还是以上述的6行8列的数字矩阵为例,若当前访问到数字45的位置,它可以从图中绿色线标出的数字的位置走过来。编程时需要注意数组越界问题,如到12、13、14的位置都只能从11的位置过来,到22的位置只能从11、12、21的位置走过来。
源码
n,m = map(int,input().split())
grid = [ list(map(int,input().split())) for i in range(n)]
''' #输入:
3 5
-4 -5 -10 -3 1
7 5 -9 3 -10
10 -2 6 -10 -4
'''
def get_lasted_loc(i_now,j_now):
'''根据当前位置(i_now,j_now)获取可能的上一个位置'''
loc_l = []
for i in range(i_now-1,i_now-4,-1):
if i >= 0:
loc_l.append( (i,j_now) )
for j in range(j_now-1,j_now-4,-1):
if j >= 0:
loc_l.append( (i_now,j) )
for ij in [(i_now-1,j_now-1),(i_now-1,j_now-2),(i_now-2,j_now-1)]:
if ij[0] >= 0 and ij[1] >= 0:
loc_l.append(ij)
return loc_l
for i_now in range(n):
for j_now in range(m):
if i_now == 0 and j_now == 0:
continue
max_ = max(grid[i][j] for i,j in get_lasted_loc(i_now,j_now))
grid[i_now][j_now] += max_
print(grid[-1][-1])
上一篇:蓝桥杯备战日志(Python)12-递增序列&等差素数列-(”找规律“枚举&数论)