我正在研究动态编程的一些评论材料。我需要提出如何划分子问题,找出基本情况,并提出递归公式。
给定n个正整数a1,a2,...,an,数k和目标W,我们想要选择一个具有k个元素的子集T,其总和最接近W.每个元素只能被选择一次。定义一个带有3个参数的子问题(即C [x,y,z] = ...)。
我只使用了一些动态编程示例,并且从未使用过在定义子问题时需要3个参数的示例。我真的迷失在这里。如果有人能发出一些很棒的光。
我对子问题的最佳猜测是:
C [x,y,z] = x来自{a1,... ay}的元素数,其中和是z
但我不知道这是否正确。
答案 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,但它有针对各种类似问题的动态编程解决方案及解释。也许这可能会给你一些想法。