9.5记忆化搜索

C++ 记忆化搜索算法详解

一、基本概念

记忆化搜索(Memoization) 是一种通过缓存子问题结果来优化递归算法的技术。核心思想是避免重复计算,将已解决的子问题结果存储起来,需要时直接取用,而非重新计算。它本质上是自顶向下的动态规划方法。

二、适用场景
  1. 递归问题存在重叠子问题:如斐波那契数列、爬楼梯问题。
  2. 状态空间可被唯一标识:每个子问题可由一组参数唯一确定。
  3. 子问题数目有限:缓存空间不会过大。
三、实现步骤
  1. 定义递归函数:明确函数参数及返回值。
  2. 设计缓存结构:选择数组、哈希表等存储结果。
  3. 检查缓存:在函数开头检查当前状态是否已计算。
  4. 递归计算并缓存:若未计算,递归求解并保存结果。
  5. 处理边界条件:确保递归终止条件正确。
四、C++ 代码示例
示例1:斐波那契数列
#include <iostream>
#include <vector>
using namespace std;

vector<int> memo;

int fib(int n) {
    if (n <= 1) return n;
    if (memo[n] != -1) return memo[n]; // 检查缓存
    memo[n] = fib(n-1) + fib(n-2);      // 计算并缓存
    return memo[n];
}

int main() {
    int n = 40;
    memo.resize(n+1, -1); // 初始化为-1表示未计算
    cout << fib(n); // 输出:102334155
    return 0;
}
示例2:0-1背包问题
#include <iostream>
#include <vector>
using namespace std;

int knapsack(int W, int wt[], int val[], int n, vector<vector<int>>& memo) {
    if (n == 0 || W == 0) return 0;
    if (memo[n][W] != -1) return memo[n][W]; // 检查缓存
  
    if (wt[n-1] > W) {
        memo[n][W] = knapsack(W, wt, val, n-1, memo);
    } else {
        int include = val[n-1] + knapsack(W - wt[n-1], wt, val, n-1, memo);
        int exclude = knapsack(W, wt, val, n-1, memo);
        memo[n][W] = max(include, exclude); // 计算并缓存
    }
    return memo[n][W];
}

int main() {
    int val[] = {60, 100, 120};
    int wt[] = {10, 20, 30};
    int W = 50;
    int n = 3;
    vector<vector<int>> memo(n+1, vector<int>(W+1, -1)); // 二维缓存
    cout << knapsack(W, wt, val, n, memo); // 输出:220
    return 0;
}
五、注意事项
  1. 状态设计:确保参数唯一标识子问题(如背包问题的物品索引和容量)。
  2. 缓存选择
    • 数组:适用于状态参数为连续整数。
    • 哈希表:适用于非连续或复合状态(需自定义哈希函数)。
  3. 初始化:将缓存初始化为特殊值(如-1),表示未计算。
  4. 栈溢出:递归深度过大会导致栈溢出,可改用迭代动态规划。
六、性能分析
  • 时间复杂度:从指数级(如O(2ⁿ))优化到多项式级(如O(nW))。
  • 空间复杂度:取决于状态空间大小(如O(n)或O(nW))。
七、进阶技巧
  1. 哈希表优化:使用unordered_map存储非连续状态。

    #include <unordered_map>
    unordered_map<string, int> cache; // 复合键转为字符串
    
  2. 尾递归优化:减少栈深度,但C++支持有限,需谨慎使用。

  3. 滚动数组:动态规划中优化空间,但记忆化搜索中较少用。

八、总结

记忆化搜索通过缓存子问题结果,显著提升递归算法效率,适用于具有重叠子问题的场景。在C++中灵活运用数组或哈希表存储状态,能有效解决复杂问题如动态规划、组合优化等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵鑫亿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值