news 2026/11/3 12:25:40

回溯法与动态规划在组合优化问题中的应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
回溯法与动态规划在组合优化问题中的应用

1. 问题背景与需求分析

小明减肥这个问题源自华为OD机考双机位A卷,是一个典型的组合优化问题。题目描述大致是:小明需要制定一个减肥计划,在给定的时间段内通过合理安排运动和饮食来达到最佳减肥效果。这实际上可以抽象为一个组合选择问题——从若干运动项目和饮食方案中选择最优组合,使得总消耗卡路里最大(或体重减少最多),同时满足时间、营养等约束条件。

这类问题在实际生活中非常常见:

  • 健身计划制定:选择训练动作和组数
  • 投资组合优化:选择股票和配置比例
  • 课程安排:选择课程和时间段

2. 算法选型思路

2.1 回溯法适用场景

回溯法特别适合解决这类需要尝试所有可能组合的问题:

  1. 解空间呈现树状结构
  2. 需要找出所有满足条件的解
  3. 问题通常有"选择/不选择"这样的决策点

在本题中,每个运动/饮食方案就是一个决策点——要么选,要么不选。

2.2 动态规划适用场景

动态规划则适用于:

  1. 问题可以分解为子问题
  2. 子问题之间存在重叠
  3. 需要最优解而非所有解

如果题目要求的是"最大减肥效果"而非"所有可能的减肥方案",DP就是更好的选择。

3. 回溯法实现详解

3.1 算法框架

def backtrack(choices, path, result, constraints): if meet_constraints(path, constraints): result.append(path.copy()) return for i in range(len(choices)): if not is_valid(choices[i], path, constraints): continue path.append(choices[i]) backtrack(choices[i+1:], path, result, constraints) path.pop()

3.2 具体实现

假设每个运动有:

  • 消耗卡路里(cal)
  • 所需时间(time)
  • 类型(type)

约束条件:

  • 总时间 ≤ max_time
  • 运动类型不能重复
def diet_backtrack(exercises, max_time): result = [] def backtrack(start, path, current_time): if current_time > max_time: return if path: result.append(path.copy()) for i in range(start, len(exercises)): ex = exercises[i] # 检查类型是否重复 if any(e['type'] == ex['type'] for e in path): continue path.append(ex) backtrack(i+1, path, current_time + ex['time']) path.pop() backtrack(0, [], 0) return result

3.3 优化技巧

  1. 提前排序:按cal/time降序排列,可以更快找到高质量解
  2. 剪枝策略:
    • 当前时间 + 剩余所有运动最小时间 > max_time时直接返回
    • 记录当前最大收益,剩余运动最大可能收益不够时剪枝

4. 动态规划实现详解

4.1 状态定义

这是一个二维背包问题:

  • 一维是时间限制
  • 一维是运动类型去重

为简化,我们先考虑时间维度: dp[i][t] = 前i个运动中,时间不超过t的最大卡路里消耗

4.2 状态转移方程

对于每个运动,有两种选择:

  1. 不选:dp[i][t] = dp[i-1][t]
  2. 选:dp[i][t] = dp[i-1][t-time] + cal

取较大值: dp[i][t] = max(dp[i-1][t], dp[i-1][t-time] + cal)

4.3 具体实现

def diet_dp(exercises, max_time): n = len(exercises) dp = [[0]*(max_time+1) for _ in range(n+1)] for i in range(1, n+1): ex = exercises[i-1] for t in range(max_time+1): if ex['time'] > t: dp[i][t] = dp[i-1][t] else: dp[i][t] = max( dp[i-1][t], dp[i-1][t-ex['time']] + ex['cal'] ) # 回溯找出具体方案 res = [] t = max_time for i in range(n, 0, -1): if dp[i][t] != dp[i-1][t]: res.append(exercises[i-1]) t -= exercises[i-1]['time'] return dp[n][max_time], res[::-1]

4.4 空间优化

可以压缩为一维数组:

def diet_dp_optimized(exercises, max_time): dp = [0]*(max_time+1) for ex in exercises: for t in range(max_time, ex['time']-1, -1): dp[t] = max(dp[t], dp[t-ex['time']] + ex['cal']) return dp[max_time]

5. 两种算法对比

维度回溯法动态规划
时间复杂度O(2^n)O(n*max_time)
空间复杂度O(n)递归栈O(n*max_time)或O(max_time)
适用场景需要所有解需要最优解
优势实现简单,能找到所有解效率高,适合大数据量
劣势数据量大时性能差只能得到一个最优解

6. 实际应用中的注意事项

  1. 数据预处理很重要:

    • 去除明显不合理的运动(如时间>max_time的)
    • 对相似运动进行分组
  2. 约束条件的处理:

    # 示例:增加营养约束 def is_valid(path, new_exercise): total_protein = sum(e['protein'] for e in path) + new_exercise['protein'] return total_protein <= max_protein
  3. 性能优化实践:

    • 对于DP,如果max_time很大,可以按比例缩放时间单位
    • 对于回溯,使用记忆化存储中间结果
  4. 结果后处理:

    • 对相似方案进行去重
    • 按效果排序输出

7. 扩展思考

  1. 多目标优化:同时考虑减重和增肌

    • 可以引入Pareto最优解概念
    • 修改DP状态为二维:dp[t][protein]
  2. 连续时间版本:

    • 当运动时间可分割时,变为分数背包问题
    • 使用贪心算法解决
  3. 长期计划制定:

    • 考虑每周计划而非单日
    • 加入恢复时间等约束

这个题目虽然以"减肥"为背景,但其核心是经典的组合优化问题。在实际面试中,面试官更关注的是:

  • 能否正确识别问题类型
  • 算法选择的合理性
  • 边界条件的处理
  • 代码实现的规范性

建议在理解这个题目的基础上,继续练习:

  • 力扣39题:组合总和
  • 力扣416题:分割等和子集
  • 力扣494题:目标和

这些题目都能帮助你深化对回溯和DP的理解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/3 12:25:12

OpenSSH 9.2 升级实战:源码编译、RPM 打包与灰度回滚

SSH 升级这件事&#xff0c;只要你动过一次生产环境的 sshd&#xff0c;就会明白它跟装个 Nginx 完全不是一个量级的操作。Nginx 挂了&#xff0c;用户抱怨一句&#xff1b;sshd 挂了&#xff0c;你自己都进不去机器。所以当安全扫描报告里那串版本号被标红、合规审计要求把 SS…

作者头像 李华
网站建设 2026/11/3 12:25:10

AI工程从零开始:构建可验证的环境、数据与服务契约

1. 这不是“搭积木”&#xff0c;而是重新校准AI工程的底层罗盘“AI Engineering from Scratch”——看到这个标题&#xff0c;我第一反应不是兴奋&#xff0c;而是下意识摸了摸自己电脑里那几个积压三年没更新的Docker镜像、三套互相冲突的Python环境、还有被注释掉一半的Kube…

作者头像 李华
网站建设 2026/11/3 12:23:41

边坡变形监测技术:毫米波雷达与北斗定位实战解析

1. 边坡变形预测&#xff1a;工程安全的第一道防线在崇山峻岭间穿行的高速公路&#xff0c;依山而建的水电站大坝&#xff0c;这些重大基础设施背后都隐藏着一个看不见的威胁——边坡失稳。2013年甘肃舟曲特大滑坡、2015年深圳光明新区渣土场滑坡等事故&#xff0c;用惨痛代价告…

作者头像 李华
网站建设 2026/11/3 12:23:22

PHP极简统计系统:宝塔本地部署与优化指南

1. 项目概述 "PHP网站统计系统 极简统计 支持宝塔本地部署"是一个轻量级的网站流量分析工具&#xff0c;专为中小型网站运营者设计。我在实际部署和使用过程中发现&#xff0c;这套系统完美解决了传统统计工具过于臃肿、数据延迟高的问题&#xff0c;特别适合需要快速…

作者头像 李华
网站建设 2026/11/3 12:21:54

Eclipse缺失Server选项的解决方案与配置指南

1. Eclipse缺失Server选项的常见场景分析 作为一名使用Eclipse多年的Java开发者&#xff0c;我经常遇到新手同事询问"为什么我的Eclipse没有Server选项&#xff1f;"这个问题看似简单&#xff0c;但背后可能涉及多种原因。最常见的情况是&#xff1a; 安装了错误的E…

作者头像 李华
网站建设 2026/11/3 12:20:20

基于多元宇宙算法的配电网故障定位优化方案

1. 项目背景与核心价值 配电网作为电力系统末端直接面向用户的关键环节&#xff0c;其可靠运行直接影响供电质量。传统故障定位方法在面对分布式电源大量接入的主动配电网时&#xff0c;常因网络结构复杂、故障信息不完整导致定位精度下降。我们团队基于多元宇宙算法&#xff0…

作者头像 李华