动态编程的问题

时间:2012-03-25 17:08:41

标签: algorithm dynamic-programming knapsack-problem partition-problem

我在理解动态编程方面遇到了困难,所以我决定解决一些问题。我知道基本的动态算法,如最长的常见子序列,背包问题,但我知道它们因为我读过它们,但我不能自己想出一些东西: - (

例如,我们有自然数的子序列。我们可以使用加号或减号的每个数字。最后,我们取这个总和的绝对值。对于每个子序列,找到尽可能低的结果。

in1:10 3 5 4; out1:2

in2:4 11 5 5 5; out2:0

in3:10 50 60 65 90 100; out3:5

第3次解释:5 = | 10 + 50 + 60 + 65-90-100 |

更糟糕的是,我的朋友告诉我这是简单的背包问题,但我在这里看不到任何背包。动态编程有些困难,还是只有我遇到大问题?

3 个答案:

答案 0 :(得分:5)

正如amit所指出的,这个算法可以理解为partition problem的一个实例。有关简单的实现,请查看此Python代码:

def partition(A):
    n = len(A)
    if n == 0:
        return 0
    k, s = max(A), sum(A)/2.0
    table = [0 if x else 1 for x in xrange(n*k)]
    for i in xrange(n):
        for j in xrange(n*k-1, -1, -1):
            if table[j-A[i]] > table[j]:
                table[j] = 1
    minVal, minIdx = float('+inf'), -1
    for j in xrange(int(s)+1):
        if table[j] and s-j < minVal:
            minVal, minIdx = s-j, j
    return int(2*minVal)

当使用问题中的一个输入调用时:

partition([10, 50, 60, 65, 90, 100])

它将按预期返回5。为了完全理解解决方案背后的数学原理,请查看此examples并单击“平衡分区”链接。

答案 1 :(得分:2)

这里的背包对于每个元素都是weight = value = number

您的绑定W1/2 * sum(elements)

这个想法是 - 你希望最大化你“挑选”的数字量而不超过1/2 * sum(elements)的限制,这正是value=weight的背包。

这个问题实际上是partition problem,这是subset sum problem的一个特例。

分区问题说:“是否有可能获得精确到一半的元素子集?”
从这里推导出你的问题很简单 - 如果有,请将这些作为+,将那些作为-取出,然后得到out = 0。 [另一种方式相同]。因此,您描述的问题是分区问题的优化。

答案 2 :(得分:0)

这与Tug Of War中的问题相同,没有平衡团队规模的限制(这是不相关的): http://acm.uva.es/p/v100/10032.html

我用自上而下的方法解决了这个问题。它适用于给定数字的上限的约束。你有上限还是数字不受限制?如果它们不受约束,我不会看到如何通过动态编程来解决这个问题。