Python算法题调试求助:N*N数组最长移动路径步数计算问题
Python算法题调试求助:N*N数组最长移动路径步数计算问题
嘿,我来帮你梳理下代码里的问题,以及怎么修正它~
首先,你的核心问题出在循环变量的修改和逻辑结构上:你在for d in range(4)的循环里直接修改了外层for i和for j的i、j变量,这会彻底打乱外层循环的迭代逻辑,而且当前的步数统计方式也不对——每个起点应该单独计算自己的移动步数,而不是把所有移动都累加到同一个count里。
先拆解你代码里的几个关键bug:
- 循环变量被意外修改:你在d循环里写了
ni, i = i, ni和nj, j = j, nj,这直接把外层循环的i、j改成了下一个位置的坐标。比如原来的i,j是起点(2,2)(对应49),当d循环到某个方向找到下一个位置后,外层的i,j已经变成了新位置,下一次d循环会在新位置继续走,但外层的i,j循环本来是要遍历所有起点的,这就完全乱了。 - 步数统计逻辑错误:你用了一个全局的count变量累加所有移动,但每个起点的步数是独立的,比如起点A走了4步,起点B走了5步,你需要分别记录这两个数,再取最大值,而不是把4+5加起来。
- “选择最小邻居”的逻辑没实现:你当前的
small_list_arr是在每个d循环里逐个添加元素,然后判断当前arr[ni][nj]是不是small_list_arr的最小值,这逻辑不对——应该先把所有合法的更小邻居都收集完,再在里面找最小的那个,然后才移动过去,而不是边遍历边判断。
修正思路:
对每个起点(i,j),单独计算它的移动步数:
- 从当前位置出发,先收集所有四个方向中在数组范围内且值比当前值小的邻居;
- 如果没有这样的邻居,步数就是0;
- 如果有,在这些邻居里找到值最小的那个位置,然后移动到该位置,步数加1,重复这个过程直到不能移动;
- 把所有起点的步数收集起来,取最大值就是答案。
修正后的代码示例
我给你写一个修正后的版本,带注释:
import sys sys.stdin = open('input.txt', 'r') # 方向数组,上下左右 di = [-1, 1, 0, 0] dj = [0, 0, -1, 1] def calculate_steps(i, j, arr, N): """计算从(i,j)出发的最大移动步数""" steps = 0 current_i, current_j = i, j while True: # 收集所有合法的更小邻居:(值, 坐标i, 坐标j) neighbors = [] for d in range(4): ni = current_i + di[d] nj = current_j + dj[d] if 0 <= ni < N and 0 <= nj < N: if arr[ni][nj] < arr[current_i][current_j]: neighbors.append( (arr[ni][nj], ni, nj) ) # 如果没有邻居,结束循环 if not neighbors: break # 找到值最小的邻居(因为所有数都不同,不用考虑并列最小的情况) neighbors.sort() min_val, next_i, next_j = neighbors[0] # 移动到下一个位置,步数加1 steps += 1 current_i, current_j = next_i, next_j return steps T = int(input()) for test_case in range(1, T + 1): N = int(input()) arr = [list(map(int, input().split())) for _ in range(N)] max_step = 0 # 遍历每个起点 for i in range(N): for j in range(N): current_step = calculate_steps(i, j, arr, N) if current_step > max_step: max_step = current_step print(f'#{test_case} {max_step}')
针对你debug时的疑问:
你之前遇到的d不重新从0开始的问题,本质是因为你在d循环里修改了外层的i,j,导致外层循环的i,j已经不是原来的起点了,下一次d循环是在新位置继续d的迭代,而不是重新开始。现在的修正版本里,每个起点的路径计算是在独立的calculate_steps函数里完成的,用current_i和current_j来跟踪当前位置,完全不会干扰外层的i,j循环,自然就不会有这个问题了。
进阶优化(可选):
如果N比较大,上面的暴力方法会有重复计算(比如多个起点可能走到同一个位置,重复计算该位置的步数),可以用记忆化搜索来优化:用一个二维数组memo,记录每个位置(i,j)出发的最长步数,计算过一次后就直接用,不用再走一遍。比如:
# 记忆化版本的辅助函数 def calculate_steps_memo(i, j, arr, N, memo): if memo[i][j] != -1: return memo[i][j] neighbors = [] for d in range(4): ni = i + di[d] nj = j + dj[d] if 0 <= ni < N and 0 <= nj < N and arr[ni][nj] < arr[i][j]: neighbors.append( (arr[ni][nj], ni, nj) ) if not neighbors: memo[i][j] = 0 return 0 # 找到最小的邻居 neighbors.sort() min_val, next_i, next_j = neighbors[0] # 递归计算下一个位置的步数,加1 res = 1 + calculate_steps_memo(next_i, next_j, arr, N, memo) memo[i][j] = res return res # 主循环里调用记忆化版本 T = int(input()) for test_case in range(1, T + 1): N = int(input()) arr = [list(map(int, input().split())) for _ in range(N)] memo = [[-1 for _ in range(N)] for _ in range(N)] max_step = 0 for i in range(N): for j in range(N): current_step = calculate_steps_memo(i, j, arr, N, memo) if current_step > max_step: max_step = current_step print(f'#{test_case} {max_step}')
备注:内容来源于stack exchange,提问作者ccccc
相关产品推荐
相关产品推荐

