【问题标题】:How can I apply memoization to this recursive function?如何将记忆应用于此递归函数?
【发布时间】:2020-10-21 19:48:23
【问题描述】:

我正在解决子集总和问题:“给定一组数字,检查它是否可以分成两个子集,使得两个子集中的元素之和相同。”对于这个问题,我创建了一个可以正常工作但无法正确记忆的递归函数。

代码是:

bool func(int a[], int i, int n, long sum) // i is 0, n is the array size, sum is required sum
{

    if(sum<0||i>=n)
      return 0;
    if(sum==0)
      return 1;

    if(func(a,i+1,n,sum-a[i]))
      return 1;
    if(func(a,i+1,n,sum))
      return 1;

    return 0;
}

请帮忙记下这段代码。您还可以告诉带有记忆或制表的递归代码哪种类型的问题更好。

【问题讨论】:

  • 除此之外:truefalsebool 文字,10ints
  • 提示:an 是递归中的常量,isum 是变量。所以你需要一个二维数组来存储i ([0, n)) 的所有可能值和 sum ([0, sum]) 的所有可能值。我个人认为 memoization 使算法更容易理解——假设你有一个现成的 memoization 库。如果没有,制表可能会更容易实现。
  • @VincentvanderWeele 你能告诉我什么是现成的记忆库
  • 这将是一个函数(模板)func_t memoise(func_t);,给定using func_t = std::function&lt;bool(int*, int, int, long)&gt;;
  • 旁白2:我觉得你的函数不对,第二个递归调用应该有sum+a[i],前面的check应该是if (i == n) return sum == 0;

标签: c++ algorithm c++11 recursion dynamic-programming


【解决方案1】:

制表要容易得多。

bool ss(int a[],int n,int s){
  bool r[n+1][s+1];
  for(int i=0;i<=n;++i)
     r[i][0]=true;
  for(int i=1;i<=s;++i)
     r[0][s]=false;
  for(int i=1;i<=n;++i)
    for(int j=1;j<=s;++j)
      if(j>=a[i])
       r[i][j]=r[i-1][j] || r[i-1][j-a[i]];
      else r[i][j]=r[i-1][j];
  return r[n][s];
}

【讨论】:

    【解决方案2】:

    记忆只是意味着存储已经计算的结果,这样您以后就不必重新计算它们。因此,每当func 调用自身并获得答案时,将条目添加到将func 的输入映射到其输出的字典中。然后,在调用 func 之前,查看字典中是否已经有您要使用的输入的条目,如果是,请不要再次调用 func;相反,请使用您在字典中缓存的输出。

    【讨论】:

      猜你喜欢
      • 2014-10-31
      • 2010-09-20
      • 2012-11-26
      • 2022-12-03
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      相关资源
      最近更新 更多