动态规划子集算法

时间:2012-06-27 01:22:38

标签: algorithm dynamic-programming

我正在研究动态编程的一些评论材料。我需要提出如何划分子问题,找出基本情况,并提出递归公式。

给定n个正整数a1,a2,...,an,数k和目标W,我们想要选择一个具有k个元素的子集T,其总和最接近W.每个元素只能被选择一次。定义一个带有3个参数的子问题(即C [x,y,z] = ...)。

我只使用了一些动态编程示例,并且从未使用过在定义子问题时需要3个参数的示例。我真的迷失在这里。如果有人能发出一些很棒的光。

我对子问题的最佳猜测是:

C [x,y,z] = x来自{a1,... ay}的元素数,其中和是z

但我不知道这是否正确。

2 个答案:

答案 0 :(得分:2)

将此分解为三个参数的一种方法是:

x: maximum index of item considered for inclusion in subset
n: number of items in subset
s: sum of subset

基本情况是C [0,0,0] =真,C [0,i> 0,j> 0] =假

递归案例是:

C[i,n+1,s+a_i] = C[i-1,n,s]  // use item i
C[i,n,s] = C[i-1,n,s] // dont use item i

这使用空间O(n ^ 2 * max(a_i))(可以通过丢弃C [i,]来减少为O(n * max(a_i)) )

然后在z附近搜索C [n,i,j]以获得最终答案。

作为循环...

for (int i = 1; i <= n; i++)
{
    C[i,n+1,s+a_i] ||= C[i-1,n,s];
    C[i,n,s] ||= C[i-1,n,s];
}

作为递归函数:

bool C(int maxindex, int size, int sum)
{
    if (memoize(maxindex, size, sum))
         return cached;

    if (maxindex == 0)
        return (size == 0 && sum == 0);

    return
         C(maxindex-1, size-1, sum - A[maxindex]) ||  // version using A[maxindex]
         C(maxindex-1, size, sum); // version not using A[maxindex]
}

答案 1 :(得分:0)

在这种情况下,我让C(x,y,z)成为一个布尔值,表示是否可以使用{a1 ... ax}中的y精确得到z的总和。

虽然它不是完全相同的问题Wikipedia,但它有针对各种类似问题的动态编程解决方案及解释。也许这可能会给你一些想法。