当前位置: 首页 > news >正文

回溯法的两种实现方式(迭代与递归)本质上都是对解空间树进行深度优先搜索(DFS),区别在于控制搜索过程的机制不同

回溯法的两种实现方式(迭代与递归)本质上都是对解空间树进行深度优先搜索(DFS),区别在于控制搜索过程的机制不同:

  • 迭代方式使用显式栈(或变量k模拟栈顶)管理当前搜索深度,通过循环和手动增减k实现“前进”与“回溯”,避免函数调用开销,空间可控但逻辑较复杂;
  • 递归方式利用系统调用栈天然支持状态保存与自动回溯,代码简洁、符合问题直观结构,但存在栈溢出风险(深度过大时)且额外开销略高。

限界函数(Bounding Function)是回溯法优化的关键——它不同于约束函数(Constraint Function,用于判断当前部分解是否满足问题基本约束),而是面向优化目标(如最大价值、最短路径等),在扩展结点前预估其子树中可能达到的最优值上界(对最大化问题)或下界(对最小化问题)。若该估计值不优于当前最优解,则剪枝。例如在 0-1 背包问题中,常用贪心上界(对剩余物品按单位重量价值降序装入,允许分数装入)作为限界函数,因其计算快且紧致性较好。

# 示例:0-1背包问题的限界函数(最大化价值,w[i], v[i]为重量与价值,cap为剩余容量)defbound(i,cap,current_value,w,v):# i: 当前考虑第i个物品(0-indexed),剩余容量cap,当前已获价值current_valuebound_val=current_value remaining_cap=cap j=iwhilej<len(w)andremaining_cap>0:ifw[j]<=remaining_cap:bound_val+=v[j]remaining_cap-=w[j]else:# 分数装入(贪心上界)bound_val+=v[j]*(remaining_cap/w[j])breakj+=1returnbound_val

在迭代回溯中,需显式模拟递归栈的行为,为每一层深度 $ k $ 维护:

  • 当前候选集合 $ S_k $(通常用列表、队列或迭代器表示);
  • 已选元素 $ x_k $(或当前尝试的候选索引);
  • 有时还需保存部分解状态(如已选物品总重/总价值)以支持约束/限界判断。

常用实现策略
✅ 使用stack,每个元素为元组(k, S_k, next_index, state),其中:

  • k: 当前深度(第kkk个位置,从 1 开始);
  • S_k: 候选集合(可预生成列表,如candidates[k],或动态计算);
  • next_index: 下一个待尝试的候选在S_k中的下标(避免重复构造集合);
  • state: 可选,如当前解的部分信息(如背包已用容量、皇后已占列集合等),用于快速验证约束/计算限界。

以下为通用伪代码框架(支持约束检查与限界剪枝):

1 stack ← empty stack 2 k ← 1 3 S₁ ← generate_candidates_for_level(1) // 初始候选集,如 {1,2,...,n}(n皇后) 4 push(stack, (k, S₁, 0, initial_state)) // next_index=0 表示将尝试 S₁[0] 5 6 while stack is not empty do 7 (k, S_k, idx, state) ← pop(stack) 8 if idx ≥ |S_k| then continue // 本层候选已穷尽,跳过(自动回溯) 9 10 x_k ← S_k[idx] 11 new_state ← update_state(state, x_k) // 如:add_queen(row=k, col=x_k), or add_weight=w[k] 12 13 if not is_feasible(new_state) then // 约束函数:剪去不满足基本条件的分支 14 push(stack, (k, S_k, idx + 1, state)) // 尝试下一个候选 15 continue 16 17 if is_complete_solution(new_state) then 18 output solution from new_state 19 continue 20 21 bound_val ← bound_function(k+1, new_state) // 限界函数:估计扩展后的最优可能值 22 if bound_val ≤ current_best_value then // 剪枝:不可能更优 23 push(stack, (k, S_k, idx + 1, state)) 24 continue 25 26 // 可扩展:进入下一层 k+1 27 S_{k+1} ← generate_candidates_for_level(k+1, new_state) 28 push(stack, (k, S_k, idx + 1, state)) // 本层留痕:下次试下一个x_k 29 push(stack, (k+1, S_{k+1}, 0, new_state)) // 深入下一层,从首个候选开始

📌关键设计说明

  • 第 8 行处理“本层无更多候选”,自然回溯到上层(因上层状态已在栈中);
  • 第 13–15 行是约束剪枝(如皇后冲突、超重);
  • 第 21–24 行是限界剪枝(仅对优化问题);
  • 第 27–29 行体现“深度优先”:先压入本层后续任务,再压入子层任务(栈后进先出,确保子层先执行);
  • generate_candidates_for_level()可依据new_state动态剪枝(如 n 皇后中排除已占列、对角线),提升效率。
http://www.jsqmd.com/news/412568/

相关文章:

  • WPF implement DelCommand inherited from ICommand from scratch
  • **0-1 背包问题的分支限界法(Branch and Bound)求解框架**,核心融合了**贪心松弛上界估计**与**精确剪枝策略**
  • N9e配置电话告警,实现故障的电话(语音)通知
  • Grafana + Loki 使用说明
  • windows上子系统WSL下载和使用
  • linux系统 Qt 通常的目录结构
  • 算法备案分类详细及合规要点整理(2026年更新版)
  • MySQL数据库从win导出成_db.sql复制到linux
  • EC2 使用 dnsmasq 本地缓存 + EKS 使用 NodeLocalDNS
  • 基于 Kubernetes + Helm 部署高可用 ETCD 集群
  • OS 核心知识点全解析(一)
  • Redis 迁移方案-RedisShake
  • qml可拖动折线图
  • 【linuxqt】qsql_mysql.cpp:57:10: fatal error: QtSql/private/qsqldriver_p.h: No such file or directory
  • 我草我怎么这么牛
  • 基于 AWS Global Accelerator 实现全球低延迟访问-RapidX 全球加速方案
  • day96(2.25)——leetcode面试经典150
  • 【Linux】进程的页表详解
  • YOLO26最新创新改进系列:主干网络全新设计——EfficientNetV2-BackBone ,引入渐进式学习策略、自适应正则强度调整机制,共同优化训练速度和参数效率,全方位提升模型检测性能!!
  • YOLO26最新创新改进系列:融入AKConv(可改变核卷积),加强特征提取,任意数量的参数和任意采样形状,为网络开销和性能之间的权衡提供了更丰富的选择。 拉升检测性能!
  • 瑞芯微开发板开机自启动设置
  • FastAsyncWorldEdit zh-cn strings.json 中文汉化
  • **0-1 背包问题中回溯法的搜索过程、通用解题步骤及两种算法实现框架(递归与非递归)**,是算法设计与分析中的经典范例
  • SRE 团队体系建设之路
  • 惊叹!大数据数据增强如何颠覆传统模式
  • int[] 与 integer[] 相互转换
  • Amazon EMR 高可用 EMR 部署注意事项及关键配置
  • SolidPlant 2020管道设计软件安装包(含详细图文教程)|兼容SolidWorks 2017及以上版本
  • 【踩坑】MacOS26上的浏览器无法显示麦克风/摄像头列表
  • 【DFS】BISHI77数水坑