【问题标题】:implement DP for a recursive function为递归函数实现 DP
【发布时间】:2012-07-03 07:11:48
【问题描述】:

我有以下递归函数:

typedef unsigned long long ull;

ull calc(ull b, ull e)
{
  if (!b) return e;
  if (!e) return b;
  return calc(b - 1, e - 1) + calc(b - 1, e) - calc(b, e - 1);
}

我想用动态编程(即使用存储)来实现它。我曾尝试使用map<pair<ull, ull>, ull>,但它也太慢了。我也无法使用数组O(1) 来实现它。

我想找到一个解决方案,以便此函数可以快速解决大型b, es。

【问题讨论】:

  • 我不确定我的问题是否正确,所以你能澄清一下你到底想要什么:你想摆脱递归,还是只想改变你的存储方式数据?
  • @SingerOfTheFall 我理解递归,但我想加快这个函数的速度
  • 明显的优化是使用缓存,可能实现为哈希映射。
  • 你不能这样做吗 DP[0][e] = e DP[b][0] = b 然后 DP[b][e] = DP[b-1] [e-1] + DP[b-1][e] - DP[b][e-1]
  • @sukunrt 那么DP[0][0]的值是多少??

标签: c++ c algorithm dynamic-programming memoization


【解决方案1】:

制作一个表格 b/e 并逐个单元格地填充它。这是空间和时间复杂度为 O(MaxB*MaxE) 的 DP。

Ante 在评论中的提议可能会降低空间复杂性 - 只存储两个需要的行或列。

0 1 2 3 4 5
1 0 3 . . .
2 . . . . .
3 . . . . .
4 . . . . .

【讨论】:

  • 比我快 15 秒 :)。
  • 存储当前和最后一行或列就足够了。所需空间为 O(min(MaxB,MaxE))。
【解决方案2】:

如果你想要一个自下而上的表示,那么这会很好。

按照 MBo 所示填写表格

这可以这样做:

for e from 0 to n:
  DP[0][e] = e
for b from 0 to n:
  DP[b][0] = b
for i from 1 to n:
   for j from 1 to n:
      DP[i][j] = DP[i-1][j-1] + DP[i-1][j] - DP[i][j-1]

现在你对任何 b,e 的回答都是 DP[b][e]

【讨论】:

  • DP[0][0] 一次 == e 然后 == b ??
  • 两次都是 0。没有区别。
【解决方案3】:

您可能想在通用自动memoization 上查看最近的blog posting。作者讨论了各种数据结构,如std::mapstd::unordered_map 等。警告:使用大量模板代码。

【讨论】:

    【解决方案4】:

    您可以使用二维数组在 O(n^2) 中实现(假设 n 作为 b 和 e 的最大值数)。 i,j 的每个当前值将取决于 i-1,j 和 i-1,j-1 和 i,j-1 处的值。确保处理 i=0, j=0 的情况。

    【讨论】:

    • 好吧,如果我们看 b, e 它们可以有 3 种情况:b > e, b
    • 你是自下而上的,所以这种情况不会发生。你能举个例子解释一下吗?
    猜你喜欢
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    • 2020-08-27
    相关资源
    最近更新 更多