递归问题常常作为中等难度题目进行考查,经过博主对递归的研究,递归可大致分为“字符串”递归和“地图查找”递归,两种递归解决办法大同小异,原理都是深度优先算法。
题目描述
给你一个由0、1(银),2(金)组成的地图,
矿堆只能由上下左右相邻的金矿或银矿连接形成。超出地图范围可以认为是空地。
假设银矿价值1,金矿价值2,请找出地图中最大价值的矿堆并输出该矿堆的价值。
输入
地图元素信息:
22220
00000
00000
11111
地图最大范围 300 * 300
输出
矿堆的最大价值
示例1
输入
22220
00000
00000
11111
输出
8
说明
该地图中有两个矿堆,价值分别为8和5,故最大价值为8
示例2
输入
22220
00001
11101
01111
输出
9
说明
该地图有两个矿堆,价值分别为8和9,故最大价值为9
解题思路及代码
该题属于“地图型”加“过程型”递归问题。与其他递归题目不同的是,该题不知道起点在哪,故需要循环遍历每个点来找出所有矿堆。还有一个重点是问题解不应参与递归函数的参数变化,其原因是该值需要在递归完成后输出,由累加而得,而在递归函数中变化的参数最终都会回归原始。
代码如下(示例):
way = []
while 1:
s = input()
if str(s) == '':
break
way.append(list(map(int, list(s))))
m = len(way)
n = len(way[0])
def dfs(x, y):
global way, m, n
if x < 0 or x == m or y < 0 or y == n or way[x][y] == 0: # 这步是递推停止的条件,在地图中常作为障碍物或者走过的地方
return 0
res = 0 # 当前这个点的价值为0
res += way[x][y] # 加上该点的价值
way[x][y] = 0 # 走过后的地方不再走,否则会反复来这里
res += dfs(x + 1, y) # 四个方向观察是否有不为0的值
res += dfs(x - 1, y)
res += dfs(x, y + 1)
res += dfs(x, y - 1)
return res
output = 0
for i in range(m):
for j in range(n):
if way[i][j] != 0:
cnt = dfs(i, j)
output = max(output, cnt)
print(output)
关键代码
while 1:
s = input()
if str(s) == '':
break
way.append(list(map(int, list(s)))) # 在不知道输入行数的前提下,我们采用判断该输入是否为空的方式来确定输入行数
————————————————————————————————————————————————————————————————————————————
if x < 0 or x == m or y < 0 or y == n or way[x][y] == 0: # 这步是递归停止的条件,在地图中常作为障碍物或者走过的地方
return 0
res = 0 # 当前这个点的价值为0
res += way[x][y] # 加上该点的价值
way[x][y] = 0 # 走过后的地方不再走,否则会反复来这里
res += dfs(x + 1, y) # 四个方向观察是否有不为0的值
res += dfs(x - 1, y)
res += dfs(x, y + 1)
res += dfs(x, y - 1)
return res # 返回路途中经过的价值
# 递归可以经过地图所有合理的点,只要记录每次经过的价值即可
总结
除以上我讲到的关于“地图型”加“过程型”递归问题需要注意的地方,另一个难点是我们该如何设置函数中的return。在本题中,我们需要通过递归累加每一次经过的值,这时候就需要通过return本次递归产生的值的方式来设计return。