满足特定条件后终止递归:Matlab数独求解器终止问题咨询
嘿,我完全懂你遇到的糟心事——递归找到数独解之后还停不下来瞎跑,用error中断确实太硬核了,完全不是正经解法。其实核心思路很简单:让递归函数返回一个「是否找到解」的状态标识,一旦找到有效解,就把这个信号层层往上传递,让上层递归直接停止尝试其他可能性,自然就终止整个递归链了。
我给你拆解下具体怎么做,先拿你提到的「生成两元素向量」的递归示例改改,你一看就明白:
先看错误逻辑的问题
假设原来的递归是这样的(生成1-3的所有两元素向量):
function generateVectors(vec, pos) if pos > 2 disp(vec); return; end for num = 1:3 vec(pos) = num; generateVectors(vec, pos+1); end end
这个会输出所有6种可能,但如果我们想找到[2,3]就立刻停止,原来的写法做不到,因为递归只会一路往下跑,跑完所有分支。
改成带状态返回的正确版本
我们让函数返回一个布尔值found,表示当前分支是否找到目标:
function found = generateVectors(vec, pos, target) % 递归终止条件:向量已填满 if pos > 2 if isequal(vec, target) disp(['找到目标解:', num2str(vec)]); found = true; % 找到解,返回true else found = false; end return; end for num = 1:3 vec(pos) = num; % 递归调用,接收子分支的状态 found = generateVectors(vec, pos+1, target); % 重点:如果子分支找到解,直接返回true,不再尝试当前位置的其他数字 if found return; end end % 所有数字都试过没找到,返回false found = false; end
调用的时候用generateVectors([], 1, [2,3]),你会发现程序找到[2,3]后立刻终止,不会再输出其他向量。
把这个思路套到数独求解器上
你的数独递归函数也需要返回「是否找到解」的状态,同时可以把最终的解棋盘作为输出参数返回。大致框架是这样:
function [solved, board] = solveSudoku(board) % 找到第一个空单元格(假设0表示空) [row, col] = find(board == 0, 1); if isempty(row) % 棋盘填满,说明找到有效解 solved = true; return; end % 尝试1-9的每个数字 for num = 1:9 if isValid(board, row, col, num) % 填入当前数字 board(row, col) = num; % 递归求解下一个空单元格 [solved, board] = solveSudoku(board); % 关键:如果子递归找到解,直接返回,不再尝试其他数字 if solved return; end % 回溯:当前数字导致无解,恢复为空单元格 board(row, col) = 0; end end % 所有数字都试过,当前分支无解 solved = false; end % 辅助函数:检查当前数字填入是否合法 function valid = isValid(board, row, col, num) % 检查行、列、3x3宫是否有重复数字 valid = ~any(board(row,:) == num) && ... ~any(board(:,col) == num) && ... ~any(board((row-1)-mod(row-1,3)+1:(row-1)-mod(row-1,3)+3, ... (col-1)-mod(col-1,3)+1:(col-1)-mod(col-1,3)+3) == num); end
这个逻辑里,一旦递归到填满的合法棋盘,就会返回solved=true,上层递归收到这个信号后,会立刻跳出循环返回,不会再尝试当前单元格的其他数字,整个递归链就会逐层终止,完美解决你说的“找到解还继续跑”的问题。
对比用error的方式,这种方法不仅能优雅终止递归,还能正常返回最终的解棋盘,逻辑清晰得多,完全符合递归的设计思路。
内容的提问来源于stack exchange,提问作者RecBCD
相关产品推荐
相关产品推荐

