题目描述
顺治喜欢滑雪,这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待太监们来载你。顺治想知道在一个区域中最长的滑坡。
区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
顺治可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。
输入数据
输入的第一行表示区域的行数 R 和列数 C (1 ≤ R,C ≤ 500) 。下面是 R 行,每行有 C 个整数,代表高度 h , 0≤ h< 104 。
输出数据
输出最长区域的长度。
样例输入
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
样例输出
25
程序分析
1 题目分析1
首先要注意的是,该题目所问的是求最长的路径的长度,由于该测试数据的原因,会想到的一个思路是:从最高点出发,在四个方向中找到递减最慢的方向,以此类推,一直走到四个方向都不可以走的时候。这个思路的一个缺陷就是有时候,最长的路径并不一定是从最高点开始的;另外一个误区就是,每次减少高度最少的点也不一定是最长的路径,对于这两点一定要理解。
那么,怎么才能找到最长的路径呢?难道要以每一个地方都为起点来试一遍吗?是的,但是我们要多做一步,就是每当走过一个地方,我们要得知它能走的最长的路径长度,将该长度记录下来,这样当下一次走到该点的时候,我们就可以直接得到答案而不用再次计算了。
具体方法便是,对每一个点进行遍历,在该点的四个方向中,对于满足不超过边界且比当前高度小的点进行递归,最后选出递归后返回值最大的值,将其+1便是当前点的路径最大值。
- 我们以测试数据为例:
- 当遍历第一步的时候,发现没有其地方可以行走,记录当前的可走的最长路径为1
- 继续遍历,当走到第二部的时候,发现只能往左边走,走到1的位置时,发现1的长度为1,所以我们直接用1就可以。
- 同理,走到3的位置时,便可以直接用2 的数据
- 依此类推,当遍历到第二行时,便能记录大量的点。在当以点17为起点时,就能发现这样节省了大量的时间。
2 动态规划方程
阶段:地图上的任意一个位置
状态:设maxPath[ i ][ j ]表示(i,j)这个位置的最长路径
决策:maxPath[ i ][ j ]=max{maxPath[ i-1 ][ j ],maxPath[ i ][ j-1 ],maxPath[ i+1 ][ j ],maxPath[ i ][ j+1]}+1,
很明显有后效性,所以采用递归进行消除
class Slide:
def __init__(self, m, n, height):
self.M, self.N, self.Height = m, n, height # m行n列的矩阵
self.maxPath = [[0]*n for i in range(m)]
self.direction = {0: [1, 0], 1: [-1, 0], 2: [0, 1], 3: [0, -1]}
def isBound(self, x, y):
if 0 <= x < self.M and 0 <= y < self.N:
return 1
else:
return 0
def solve(self, x, y):
if self.maxPath[x][y]: # (x,y)的位置处理过,则返回这一点的最长路径
return self.maxPath[x][y]
self.maxPath[x][y] = 1 # (x,y)这个位置没有处理,设置这点的路径长度为1,下面再进行更改
for i in range(4):
xx = x+self.direction[i][0]
yy = y+self.direction[i][1]
if self.isBound(xx, yy) and self.Height[xx][yy] < self.Height[x][y]:
self.maxPath[x][y] = max(self.maxPath[x][y], self.solve(xx, yy)+1)
return self.maxPath[x][y]
m, n = map(int, input().split())
height = {}
for i in range(m):
temp = list(map(int, input().split()))
height[i] = temp
path = 0
slide = Slide(m, n, height)
for i in range(m):
for j in range(n):
if slide.solve(i, j) > path:
path = slide.solve(i, j)
print(path)
参考https://blog.csdn.net/a769973411/article/details/79414753 ↩︎