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

求通过置0匹配行列目标和的网格问题递归求解算法

矩阵置0满足行列目标和的回溯算法完善方案

问题描述

给定n阶二维矩阵board,以及对应行目标和数组、列目标和数组,仅通过将矩阵中元素置0的操作,使得操作后的矩阵每行元素和等于对应行目标值,每列元素和等于对应列目标值。
给出的测试用例如下:

  • 初始board:
board = [
    [5,9,4,6,1],
    [6,2,3,6,7],
    [3,4,8,4,4],
    [2,2,6,4,6],
    [7,3,1,6,5]
]
  • 行目标值:row_goal = [24,13,15,8,12]
  • 列目标值:col_goal = [8,11,13,18,22]
  • 预期输出:
board = [
    [5,9,4,6,0],
    [0,0,0,6,7],
    [3,0,8,0,4],
    [0,2,0,0,6],
    [0,0,1,6,5]
]

原代码存在的问题

你的回溯思路方向正确,但存在几个关键逻辑漏洞:

  1. 缺少row_sum()、col_sum()的实现逻辑,且每次全量计算矩阵和效率极低,也没有提前剪枝的判断逻辑
  2. 递归调用逻辑错误:对同一个单元格重复调用了两次solve_board,没有明确区分「置0」和「保留原值」两种选择的处理逻辑
  3. 没有对visited数组做回溯处理,会导致后续回溯路径无法访问已经遍历过的单元格

修正后完整实现代码

# 初始化全局变量(也可封装为类避免全局变量,此处和原有写法逻辑保持兼容)
board = [
    [5,9,4,6,1],
    [6,2,3,6,7],
    [3,4,8,4,4],
    [2,2,6,4,6],
    [7,3,1,6,5]
]
row_goal = [24,13,15,8,12]
col_goal = [8,11,13,18,22]
board_len = len(board)
# 预计算初始行列和,维护当前实时行列和,避免重复计算
init_row_sum = [sum(row) for row in board]
init_col_sum = [sum(col) for col in zip(*board)]
curr_row_sum = init_row_sum.copy()
curr_col_sum = init_col_sum.copy()

def is_cell_valid(x_coord, y_coord):
    return 0 <= x_coord < board_len and 0 <= y_coord < board_len

def choose_cell(x,y,visited):
    # 优先从当前位置往后找,减少重复遍历
    for i in range(x,board_len):
        start_j = y if i == x else 0
        for j in range(start_j, board_len):
            if visited[i][j] == 0 and is_cell_valid(i,j):
                return i,j
    # 没找到再从头遍历
    for i in range(0,board_len):
        for j in range(0, board_len):
            if visited[i][j] == 0 and is_cell_valid(i,j):
                return i,j
    return -1,-1

def solve_board(x, y, visited):
    # 终止条件1:所有行列和都符合目标
    if curr_row_sum == row_goal and curr_col_sum == col_goal:
        return True
    # 终止条件2:没有未访问的单元格,仍未满足要求
    x,y = choose_cell(x,y, visited)
    if x == -1:
        return False
    
    # 标记当前单元格为已访问
    visited[x][y] = 1
    temp = board[x][y]

    # 选择1:将当前单元格置0
    curr_row_sum[x] -= temp
    curr_col_sum[y] -= temp
    board[x][y] = 0
    # 提前剪枝:置0后行列和不能小于目标值,否则直接放弃该路径
    if curr_row_sum[x] >= row_goal[x] and curr_col_sum[y] >= col_goal[y]:
        if solve_board(x, y, visited):
            return True
    # 回溯置0的选择
    board[x][y] = temp
    curr_row_sum[x] += temp
    curr_col_sum[y] += temp

    # 选择2:保留当前单元格原值,直接递归
    if solve_board(x, y, visited):
        return True
    
    # 两种选择都失败,回溯visited标记,返回失败
    visited[x][y] = 0
    return False

# 调用执行
visited = [[0]*board_len for _ in range(board_len)]
if solve_board(0,0, visited):
    print("求解成功,结果为:")
    for row in board:
        print(row)
else:
    print("无符合要求的解")

逻辑说明

  1. 新增实时行列和维护,避免每次递归全量计算矩阵和,大幅提升运行效率
  2. 对每个单元格明确处理两种选择:置0/保留原值,每种选择执行后递归,失败则回溯状态
  3. 增加剪枝逻辑:置0后如果行或列的和小于目标值,直接放弃该路径,不需要继续递归
  4. 修正visited数组的回溯逻辑,所有路径尝试失败后会恢复单元格的未访问标记,不影响其他回溯路径
    运行上述代码即可得到你给出的预期输出结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:54:08