【发布时间】:2018-07-24 23:16:41
【问题描述】:
我正在探索动态编程设计方法如何与问题的基本组合属性相关联。
为此,我正在查看硬币兑换问题的典型实例:让S = [d_1, d_2, ..., d_m] 和n > 0 成为请求的金额。除了S 中的元素,我们可以通过多少种方式将n 相加?
如果我们遵循动态规划方法来设计一个算法来解决这个问题,该算法将允许具有多项式复杂性的解决方案,我们将首先查看问题以及它与更小和更小的问题之间的关系。更简单的子问题。这将产生一个递归关系,描述一个归纳步骤,根据其相关子问题的解决方案来表示问题。然后我们可以实现 memoization 技术或 制表 技术,以在 top-down 或 bottom 中有效地实现这种递归关系向上 方式,分别。
递归关系可能如下(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 + 12 + 1 + 1 + 1 + 11 + 2 + 1 + 1 + 11 + 1 + 2 + 1 + 11 + 1 + 1 + 2 + 11 + 1 + 1 + 1 + 22 + 2 + 1 + 11 + 2 + 2 + 11 + 1 + 2 + 22 + 1 + 2 + 11 + 2 + 1 + 22 + 1 + 1 + 22 + 2 + 26
假设顺序无关紧要,我们可以计算以下解决方案:
1 + 1 + 1 + 1 + 1 + 12 + 1 + 1 + 1 + 12 + 2 + 1 + 12 + 2 + 26
从动态规划的角度解决问题时,如何控制顺序?具体来说,我该如何编写函数:
count_with_order()count_wout_order()
?
是否对顺序问题的需求意味着选择修剪后的回溯而不是动态编程方法?
【问题讨论】:
标签: python algorithm dynamic-programming combinatorics memoization