题目描述:
给定一个n*m矩阵A,矩阵中每个元素Aij为一个16进制数。寻找一条从左上角到右下角的路径,每次只能向右或者向下移动,使得路径上所有数字之积在16进制下的后缀0最少。(乘积包含开始和结束位置)
输入输出例子忘记保存了。遗憾之处,在计算0的时候忘记写break语句了。还要多练习。
Python实现(深度优先搜索dfs):
# Bytedance AI Camp 2018 -编程题1-(北京时间)05月26日 09时30分-05月26日 12时00分
# 解题思路 深度优先搜索,用栈实现,符合的路径一直入栈,直到找到出口,计算后缀0的个数,并更新数据,然后出栈
# 找不到可走位置,则出栈
# @Time :2018/5/26
# @Author :LiuYinxing
def findPath(maps, n, m):
if n < 2 or n > 1000 or m < 2 or m > 1000: return None
for i in range(n): # 把16进制的数字转换成10进制
for j in range(m):
maps[i][j] = int(maps[i][j], 16)
path = [[1] * m for _ in range(n)] # 标记路径是否已经走过
st, path[0][0] = [[0, 0, -1]], 0 # 初始化栈,并标记0 0 位置已经走过
findp, min0 = [], float('inf') # 记录路径和最小后缀零的个数
while st:
i, j, di = st[-1][0], st[-1][1], st[-1][2] # 获取栈顶原始
i1, j1, find = -1, -1, 0 # 下一个可能扩展的结点
while di < 2 and find == 0:
di += 1
if di == 0: # 向右
i1, j1 = i, j + 1
elif di == 1: # 向下
i1, j1 = i + 1, j
if -1 < i1 < n and -1 < j1 < m and path[i1][j1] == 1: find = 1 # 找到
if find == 1: # 找到进栈
st[-1][2] = di # 当前栈顶的一个方向 进入下一个可走的方格
st.append([i1, j1, -1]) # 入栈
path[i1][j1] = 0 # 此位置已经走过
if st[-1][0] == n - 1 and st[-1][1] == m - 1: # 找到右下角
product, count0, tmppath = 1, 0, '' # 记录本次的乘积,后缀0的个数,和路径(字符串)
for v in st:
product *= maps[v[0]][v[1]] # 获取乘积
if v[2] == 0: tmppath += '>'
elif v[2] == 1: tmppath += 'V'
product = hex(product)
for i in range(len(product) - 1, 0, -1): # 从倒数第一个字符开始计算
if product[i] == '0': count0 += 1 # 统计后缀0的个数
else: break # 遇到不是0的字符串结束
if count0 < min0: min0, findp = count0, [tmppath] # 找到后缀0更少的,更新min0, 清空findp并添加新的值
elif count0 == min0: findp.append(tmppath) # 如果找到后缀0个数一样的,追加到findp里面
path[st[-1][0]][st[-1][1]] = 1 # 出栈
st.pop()
else:
path[st[-1][0]][st[-1][1]] = 1 # 出栈
st.pop()
print(min0)
print(sorted(findp)[0]) # 对路径排序,输出第一个
if __name__ == '__main__':
# n, m = map(int, input().split())
# maps = []
# for case in range(n):
# caption = list(map(str, input().split()))
# arr.append(caption)
n, m = 3, 3
maps = [['3', '2', '8'],
['c', '8', '8'],
['2', 'a', 'f']]
findPath(maps, n, m)
发现问题请评论指正哦。