You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python算法题调试求助:N*N数组最长移动路径步数计算问题

Python算法题调试求助:N*N数组最长移动路径步数计算问题

嘿,我来帮你梳理下代码里的问题,以及怎么修正它~

首先,你的核心问题出在循环变量的修改和逻辑结构上:你在for d in range(4)的循环里直接修改了外层for i和for j的i、j变量,这会彻底打乱外层循环的迭代逻辑,而且当前的步数统计方式也不对——每个起点应该单独计算自己的移动步数,而不是把所有移动都累加到同一个count里。

先拆解你代码里的几个关键bug:

  1. 循环变量被意外修改:你在d循环里写了ni, i = i, ni和nj, j = j, nj,这直接把外层循环的i、j改成了下一个位置的坐标。比如原来的i,j是起点(2,2)(对应49),当d循环到某个方向找到下一个位置后,外层的i,j已经变成了新位置,下一次d循环会在新位置继续走,但外层的i,j循环本来是要遍历所有起点的,这就完全乱了。
  2. 步数统计逻辑错误:你用了一个全局的count变量累加所有移动,但每个起点的步数是独立的,比如起点A走了4步,起点B走了5步,你需要分别记录这两个数,再取最大值,而不是把4+5加起来。
  3. “选择最小邻居”的逻辑没实现:你当前的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:12:57