一、回溯法分析最小重量机器设计问题
1.1 最小重量机器设计问题的解空间
解的形式:每个解是一个长度为 n 的有序元组 X = (x₁, x₂, ..., xₙ),其中 xᵢ ∈ {1, 2, ..., m}(i=1,2,...,n),xᵢ 表示 “第 i 个部件选择第 xᵢ 个供应商”。
解空间的规模:每个部件有 m 种选择,n 个部件的所有可能组合数为 mⁿ,即解空间包含 mⁿ 个候选解。
约束条件与目标函数:
约束条件:候选解对应的总价格 sum_c = c[1][x₁] + c[2][x₂] + ... + c[n][xₙ] ≤ C;
目标函数:在满足约束的解中,找到总重量 sum_w = w[1][x₁] + w[2][x₂] + ... + w[n][xₙ] 最小的解。
解空间的类型:属于笛卡尔积型解空间(每个部件的选择相互独立,构成多维集合的笛卡尔积)。
1.2 最小重量机器设计问题的解空间树
树的类型:m 叉树(每个非叶子结点有 m 个分支,对应每个部件的 m 个供应商选择)。
树的分层(按部件划分):
第 0 层:根结点,代表 “尚未选择任何部件” 的初始状态,无实际选择意义。
第 1 层:对应 “第 1 个部件” 的供应商选择,根结点延伸出 m 个分支,每个分支对应 x₁=1, x₁=2, ..., x₁=m。
第 2 层:对应 “第 2 个部件” 的供应商选择,第 1 层的每个结点都会延伸出 m 个分支,每个分支对应 x₂=1, x₂=2, ..., x₂=m。
...
第 k 层(1≤k≤n):对应 “第 k 个部件” 的供应商选择,每个结点对应前 k-1 个部件的一个确定选择,延伸出 m 个分支对应第 k 个部件的 m 种选择。
第 n 层:叶子结点,每个叶子结点对应一个完整的候选解 (x₁, x₂, ..., xₙ),即所有部件的供应商都已选定。
树的关键参数:
树的高度:n+1(从第 0 层根结点到第 n 层叶子结点)。
叶子结点数:mⁿ(与解空间规模一致,对应所有候选解)。
总结点数:1 + m + m² + ... + mⁿ = (mⁿ⁺¹ - 1) / (m - 1)(等比数列求和)。
1.3 解空间树遍历中每个结点的状态值
回溯法遍历解空间树时,每个结点对应 “已选定前 k 个部件(k 为结点所在层数,0≤k≤n)” 的中间状态,为了推进遍历和剪枝,每个结点需要记录以下核心状态值:
当前已选部件数 k(或结点层数):
标识遍历进度,k=0 对应根结点(未选部件),k=n 对应叶子结点(所有部件选完),1≤k≤n-1 对应中间结点(已选前 k 个部件)。
作用:判断是否已生成完整候选解,以及下一步需要处理第 k+1 个部件。
当前累计价格 sum_c:
记录前 k 个部件所选供应商的价格总和(sum_c = Σc[i][xᵢ],i=1到k)。
作用:剪枝的核心依据 —— 若 sum_c > C,说明该分支后续无论选择哪个供应商,总价格都会超过上限,无需继续遍历该分支的子结点,直接回溯。
当前累计重量 sum_w:
记录前 k 个部件所选供应商的重量总和(sum_w = Σw[i][xᵢ],i=1到k)。
作用:记录当前分支的重量累积,若后续遍历到叶子结点(完整解),则用该值更新全局最小重量;同时可结合 “未来剩余部件的最小可能重量” 进行优化剪枝(若 sum_w + 剩余部件最小重量 ≥ 当前全局最小重量,则该分支不可能得到更优解,直接回溯)。
当前已选供应商序列 (x₁, x₂, ..., x_k)(可选,按需记录):
记录前 k 个部件的供应商选择,用于最终输出最优解的具体方案(若问题仅要求最小重量,可省略该状态,仅记录关键数值即可)。
补充:根结点的状态值为 k=0、sum_c=0、sum_w=0、空序列。
二、对回溯算法的理解
回溯算法(Backtracking)是一种基于 “试探 - 回溯” 思想的暴力搜索算法,核心是通过遍历解空间树寻找满足条件的解(可行解或最优解),同时通过剪枝避免无效搜索,提升效率。
- 核心思想
“走不通就回头”:从根结点开始,按深度优先遍历的方式逐步选择候选解;当遍历到某一结点时,若判断该结点对应的中间状态无法生成有效解(违反约束或不可能更优),则停止遍历该结点的所有子结点(剪枝),回溯到其父结点,尝试其他分支;若遍历到叶子结点,则得到一个完整候选解,根据问题要求(可行解 / 最优解)进行记录或更新。 - 基本流程
以最小重量机器设计问题为例,回溯算法的通用流程如下:
初始化:设置全局变量(如全局最小重量min_total_w初始化为无穷大),初始化根结点状态(k=0、sum_c=0、sum_w=0)。
递归遍历(深度优先):
终止条件 1:若 k == n(遍历到叶子结点,得到完整解),若 sum_c ≤ C,则用 sum_w 更新 min_total_w,返回。
终止条件 2:若 sum_c > C(违反约束),直接返回(剪枝)。
终止条件 3:若 sum_w + 剩余部件最小重量 ≥ min_total_w(不可能更优),直接返回(优化剪枝)。
遍历当前部件的所有供应商(j=1到m):
更新状态值:k+1、sum_c + c[k+1][j]、sum_w + w[k+1][j]。
递归调用,处理下一个部件。
回溯:递归返回后,恢复状态值(如sum_c、sum_w回退到之前的状态),继续尝试当前部件的下一个供应商。
输出结果:遍历结束后,min_total_w 即为最小重量(若不存在满足约束的解,需做异常处理)。 - 关键要素
解空间:所有候选解的集合,是回溯的搜索范围(如最小重量机器设计的笛卡尔积解空间)。
解空间树:解空间的树形表示,是回溯的遍历载体(如m叉树)。
剪枝函数:回溯算法效率的核心,分为两类:
约束剪枝:过滤违反问题约束的分支(如sum_c > C);
最优性剪枝:过滤不可能得到更优解的分支(如sum_w + 剩余最小重量 ≥ 当前最优解)。 - 优势与局限
优势:
逻辑清晰,易于实现,无需复杂的数据结构;
通过剪枝大幅减少无效搜索,效率远高于纯暴力枚举;
既能求解可行解(如组合总和问题),也能求解最优解(如最小重量机器设计问题)。
局限:
本质仍是暴力搜索,当解空间规模过大(如n和m较大时,mⁿ呈指数增长),时间复杂度会急剧升高(最坏时间复杂度仍为O(mⁿ));
依赖剪枝策略的设计,若剪枝效果差,算法效率会大幅下降。