【问题标题】:Control of the combinatorial aspects of a dynamic programming solution控制动态规划解决方案的组合方面
【发布时间】:2018-07-24 23:16:41
【问题描述】:

我正在探索动态编程设计方法如何与问题的基本组合属性相关联。

为此,我正在查看硬币兑换问题的典型实例:让S = [d_1, d_2, ..., d_m]n > 0 成为请求的金额。除了S 中的元素,我们可以通过多少种方式将n 相加?

如果我们遵循动态规划方法来设计一个算法来解决这个问题,该算法将允许具有多项式复杂性的解决方案,我们将首先查看问题以及它与更小和更小的问题之间的关系。更简单的子问题。这将产生一个递归关系,描述一个归纳步骤,根据其相关子问题的解决方案来表示问题。然后我们可以实现 memoization 技术或 制表 技术,以在 top-downbottom 中有效地实现这种递归关系向上 方式,分别。

递归关系可能如下(Python 3.6 语法和基于 0 的索引):

def C(S, m, n):
    if n < 0:
        return 0
    if n == 0:
        return 1
    if m <= 0:
        return 0
    count_wout_high_coin = C(S, m - 1, n)
    count_with_high_coin = C(S, m, n - S[m - 1])
    return count_wout_high_coin + count_with_high_coin

但是,在绘制子问题 DAG 时,可以看到任何基于 DP 的算法实现这种递归关系都会产生正确数量的解决方案,但不考虑顺序。

例如,对于S = [1, 2, 6]n = 6,可以通过以下方式识别(假设订单很重要):

  1. 1 + 1 + 1 + 1 + 1 + 1
  2. 2 + 1 + 1 + 1 + 1
  3. 1 + 2 + 1 + 1 + 1
  4. 1 + 1 + 2 + 1 + 1
  5. 1 + 1 + 1 + 2 + 1
  6. 1 + 1 + 1 + 1 + 2
  7. 2 + 2 + 1 + 1
  8. 1 + 2 + 2 + 1
  9. 1 + 1 + 2 + 2
  10. 2 + 1 + 2 + 1
  11. 1 + 2 + 1 + 2
  12. 2 + 1 + 1 + 2
  13. 2 + 2 + 2
  14. 6

假设顺序无关紧要,我们可以计算以下解决方案:

  1. 1 + 1 + 1 + 1 + 1 + 1
  2. 2 + 1 + 1 + 1 + 1
  3. 2 + 2 + 1 + 1
  4. 2 + 2 + 2
  5. 6

从动态规划的角度解决问题时,如何控制顺序?具体来说,我该如何编写函数:

  • count_with_order()
  • count_wout_order()

?

是否对顺序问题的需求意味着选择修剪后的回溯而不是动态编程方法?

【问题讨论】:

    标签: python algorithm dynamic-programming combinatorics memoization


    【解决方案1】:

    每个问题都是特殊的,尽管可能有一些问题可以组合在一起。对于您的特定示例,可以通过考虑n 的解决方案数量等于每个较低可实现数字可实现的解决方案总数,即n - coin 来实现订单问题的计数(递归或列表)每个面额。

    Python 代码:

    def f(n, coins):
      if n < 0:
        return 0
    
      if n == 0:
        return 1
    
      return sum([f(n - coin, coins) for coin in coins])
    
    # => f(6, [1, 2, 6]) # 14
    

    【讨论】:

    • 这是一个很好的答案,它明确显示了如何在 DP 方法中考虑顺序的组合方面 :)
    • 我也在研究解决方案中和的奇偶性。假设我想将n 分成 2 个人。每个人得到相同数量的硬币,无论每个人得到的总和是多少。在 14 个解决方案中,只有 7 个包含偶数个硬币,这样我就可以平均分配它们。但我想排除给每个人多余的硬币分配。例如,1+2+2+11+2+1+2 是订单问题时的不同解决方案,但它们代表相同的硬币分成两个人,即人 B 将得到1+2 = 2+1。我很难想出一个递归来计算分裂。
    • 起初,我认为从总数中计算具有偶数个和数的解决方案会产生正确的非冗余拆分计数,但我现在可以看到这种推理是不正确的。
    • @Eduardo 感谢您的 cmets。也许发布一个有关您所描述的拆分的更多详细信息的问题。听起来很有趣。
    • @Eduardo 也考虑添加algorithm 标签。
    猜你喜欢
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多