华为OD机试(C卷+D卷)2024真题目录(Java & c++ & python)
题目描述
小华按照地图去寻宝,地图上被划分成 m 行和 n 列的方格,横纵坐标范围分别是 [0, n-1] 和 [0, m-1]。
在横坐标和纵坐标的数位之和不大于 k 的方格中存在黄金(每个方格中仅存在一克黄金),但横坐标和纵坐标数位之和大于 k 的方格存在危险不可进入。小华从入口 (0,0) 进入,任何时候只能向左,右,上,下四个方向移动一格。
请问小华最多能获得多少克黄金?
输入描述
坐标取值范围如下:
- 0 ≤ m ≤ 50
- 0 ≤ n ≤ 50
k 的取值范围如下:
- 0 ≤ k ≤ 100
输入中包含3个字数,分别是m, n, k
输出描述
输出小华最多能获得多少克黄金
示例1
输入
40 40 18
输出
1484
示例2
输入
5 4 7
输出
20
解题思路
简单搜索,可以深度优先搜索(DFS)也可以广度优先搜索(BFS)
从(0,0)点开始,然后进行深搜或者广搜,其上下左右四个新位置,新位置是否可以进入的条件是:
- 新位置不越界
- 新位置未被访问过
- 新位置的横坐标、纵坐标的数位之和 <= k
每进入一个位置,则获得黄金1克。
参考代码
深搜代码
import sys
# 设置递归深度
sys.setrecursionlimit(5000)
# 输入获取
rows, cols, maxSum = map(int, input().split())
# 全局变量
goldCount = 0 # 记录题解
visitedPositions = set() # 记录已访问过的位置,避免重复统计
directions = ((-1, 0), (1, 0), (0, -1), (0, 1)) # 上下左右偏移量
digitSums = [0] * max(rows, cols) # digitSums数组的索引是原始数,值是原始数对应的数位和
for i in range(len(digitSums)):
num = i
while num > 0:
digitSums[i] += num % 10
num //= 10
# 深度优先搜索遍历矩阵
def dfs(x, y):
# 如果对应位置越界,则不能进入
if x < 0 or x >= rows or y < 0 or y >= cols:
return
# 如果对应位置的横坐标、纵坐标的数位和之和超过了maxSum,则不能进入
if digitSums[x] + digitSums[y] > maxSum:
return
pos = x * cols + y
# 如果对应位置已访问过,则不能进入
if pos in visitedPositions:
return
# 否则可以进入
visitedPositions.add(pos)
# 且获得黄金
global goldCount
goldCount += 1
# 继续遍历上、下、左、右方向上的新位置继续深搜
for offsetX, offsetY in directions:
newX = x + offsetX
newY = y + offsetY
dfs(newX, newY)
# 算法入口
dfs(0, 0)
print(goldCount)
广搜代码
# 输入获取
rows, cols, maxDigitSum = map(int, input().split())
# 全局变量
visitedPositions = set() # 记录已访问过的位置,避免重复统计
directions = ((-1, 0), (1, 0), (0, -1), (0, 1)) # 上下左右偏移量
digitSums = [0] * max(rows, cols) # digitSums数组的索引是原始数,值是原始数对应的数位和
for i in range(len(digitSums)):
num = i
while num > 0:
digitSums[i] += num % 10
num //= 10
# 广度优先搜索
def bfs():
queue = [0]
# 由于maxDigitSum >= 0, 因此出发点(0,0)肯定可以访问,且有黄金
goldCount = 1
visitedPositions.add(0)
while len(queue) > 0:
pos = queue.pop(0)
x = pos // cols
y = pos % cols
# 遍历当前位置的上下左右四个方向的新位置
for offsetX, offsetY in directions:
newX = x + offsetX
newY = y + offsetY
# 新位置越界,则无法访问
if newX < 0 or newX >= rows or newY < 0 or newY >= cols:
continue
# 新位置的横坐标、纵坐标数位和之和超过maxDigitSum,则无法访问
if digitSums[newX] + digitSums[newY] > maxDigitSum:
continue
# 新位置已访问过,则不能再访问
newPos = newX * cols + newY
if newPos in visitedPositions:
continue
# 否则可以进入
goldCount += 1
visitedPositions.add(newPos)
queue.append(newPos)
return goldCount
# 算法入口
if rows == 0 or cols == 0:
print("0")
else:
print(bfs())