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

Python回溯法实现骑士巡游问题:代码异常问题求助

骑士巡游问题代码排查与修复

核心问题分析

你的代码存在三个关键问题,导致输出不符合预期且大棋盘运行效率极低:

1. 结果引用错误

找到完整解时,result.append(board)添加的是棋盘对象的引用而非副本。后续回溯修改棋盘时,已存入结果列表的所有棋盘会被同步修改,最终结果全是回溯后的未完成状态。

2. 回溯状态恢复逻辑错误

状态恢复代码(重置棋盘和坐标)的缩进错误:即使当前移动不合法(执行了continue),仍会执行坐标回退操作,破坏current_x和current_y的正确值,引发后续移动的坐标混乱。

3. 无搜索优化,大棋盘效率极低

纯递归回溯的搜索空间随棋盘规模指数级增长,对于n=8的棋盘,暴力搜索几乎无法在合理时间内找到解,必须引入启发式优化。

修复后的代码

def knight(n):
    xy_movements = [(2,1),(2,-1),(-2,1),(-2,-1),(1,2),(-1,2),(1,-2),(-1,-2)]
    board = [["."]*n for _ in range(n)]
    board[0][0] = 0
    current_x = 0
    current_y = 0
    result = []

    def backtrack(num):    
        nonlocal current_x, current_y
        if num == (n*n)-1:
            # 添加棋盘深拷贝,避免引用修改
            result.append([row.copy() for row in board])
            return
        
        for move in xy_movements:
            new_x = current_x + move[0]
            new_y = current_y + move[1]
            if 0 <= new_x < n and 0 <= new_y < n and board[new_x][new_y] == ".":
                # 执行移动并标记
                current_x, current_y = new_x, new_y
                board[current_x][current_y] = num + 1
                backtrack(num + 1)
                # 仅当执行了移动才进行状态恢复
                board[current_x][current_y] = "."
                current_x -= move[0]
                current_y -= move[1]

    backtrack(0)
    return result

关键修复点说明

  • 深拷贝结果:用[row.copy() for row in board]创建棋盘副本存入结果,避免后续修改影响已记录的解。
  • 修正缩进:将状态恢复代码移入合法移动的if块内部,确保只有执行过移动操作才回退状态,避免坐标混乱。
  • 提前计算新坐标:减少重复计算,提升代码可读性。

大棋盘优化建议

对于n≥5的棋盘,纯回溯效率极低,建议引入Warnsdorff规则优化搜索顺序:每次优先选择下一步可移动位置最少的方向,大幅减少无效搜索分支。示例优化逻辑:

def get_sorted_moves(x, y, board, n, movements):
    candidates = []
    for dx, dy in movements:
        nx = x + dx
        ny = y + dy
        if 0 <= nx < n and 0 <= ny < n and board[nx][ny] == ".":
            # 计算该候选位置的下一步可选数量
            count = 0
            for ddx, ddy in movements:
                nnx = nx + ddx
                nny = ny + ddy
                if 0 <= nnx < n and 0 <= nny < n and board[nnx][nny] == ".":
                    count += 1
            candidates.append((count, dx, dy))
    # 按可选数量升序排序,优先选择分支少的方向
    candidates.sort()
    return [(dx, dy) for _, dx, dy in candidates]

在回溯函数的循环中,用get_sorted_moves(current_x, current_y, board, n, xy_movements)替代原有的xy_movements,可大幅提升n=8时的搜索效率。

内容的提问来源于stack exchange,提问作者MathMan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:17:05