【华为OD机试 Python】递归问题之寻找最大价值的矿堆

递归问题常常作为中等难度题目进行考查,经过博主对递归的研究,递归可大致分为“字符串”递归和“地图查找”递归,两种递归解决办法大同小异,原理都是深度优先算法。


题目描述

给你一个由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。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从那开始

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值