如何在以下递归中实现动态编程?

时间:2012-10-07 13:40:56

标签: c algorithm recursion

我有以下递归:

if(a%2 == 0){
f([a1,a2,...,aN],a,N) = (a1 + aN)/2 + f([a1,a2,...,a(N-1)],a+1,N-1)/2 + 
f([a2,...,aN],a+1,N-1)/2;
}
else{
f([a1,a2,...,aN],a,N) = f([a1,a2,...,a(N-1)],a+1,N-1)/2 + 
f([a2,...,aN],a+1,N-1)/2;
}

基本案例:

f([a1,a2],a,2) = (a1+a2)/2;

显然,如果我以递归方式实现它,就会出现堆栈溢出。我应该如何利用动态编程来获得这种递归的最佳解决方案?

[a1,a2,..,aN]表示整数数组。

N的限制是2000和a1,a2,..,aN< = 999。

3 个答案:

答案 0 :(得分:3)

这有点像家庭作业问题。我建议你与讲师或TA会面,因为这是最好的互动学习的东西。如果您使用此信息,请务必引用它,以免您剽窃。

首先,观察结果在值[a0, a1, ... aN]中是线性的。因此,您实际上只需要跟踪它们的系数。出于符号目的,让我们写{b1, b2, ..., bN}来代表b1 * a1 + b2 * a2 + ... bN * aN

接下来,手动计算一些递归:

f([a1, a2], a, 2) = { 1/2, 1/2 }N=2的基本情况。

让我们看一下N=3

f([a1, a2, a3], a, 3) a偶数= {1/2, 0, 1/2} + { f([a1, a2], a+1, 2)/2, 0 } + { 0, f([a2, a3], a+1, 2)/2 } = { 1/2, 0, 1/2 } + { 1/4, 1/4, 0 } + { 0, 1/4, 1/4 } = { 3/4, 1/2, 3/4 }

{p} f([a1, a2, a3], a, 3) a奇数= { f([a1, a2], a+1, 2)/2, 0 } + { 0, f([a2, a3], a+1, 2)/2 } = { 1/2, 0, 1/2 } + { 1/4, 1/4, 0 } + { 0, 1/4, 1/4 } = { 1/4, 1/2, 1/4 }

现在N=4

f([a1, a2, a3, a4], a, 4)偶数= a

{ 1/2, 0, 0, 1/2 } + { f[a1, a2, a3], a+1, 3)/2, 0 } + { 0, f([a2, a3, a4], a+1, 3)/2 }。由于a是偶数,a+1是奇数,所以我们就是F([], even, 3)f([a1, a2, a3, a4], a, 4)偶数= a的{​​{1}}。

{p} { 1/2, 0, 0, 1/2 } + { 1/8, 1/4, 1/8, 0 } + { 0, 1/8, 1/4, 1/8 } = { 5/8, 3/8, 3/8, 5/8 } f([a1, a2, a3, a4], a, 4)奇数= a

现在您可以看到系数仅取决于{ f[a1, a2, a3], even, 3)/2, 0 } + { 0, f([a2, a3, a4], even, 3)/2 } = { 3/8, 1/4, 3/8, 0 } + { 0, 3/8, 1/4, 3/8 } = { 3/8, 5/8, 5/8, 3/8 }以及N是偶数还是奇数。

这意味着您的动态编程只需要记住a和布尔值的每个组合的系数。由于N上限为2000,这意味着您只需要4000个条目,这不应该是一个太大的负担。事实上,您可以放弃递归,只需像上面那样逐步计算整个表格。

答案 1 :(得分:0)

您需要存储所有a,N值对的答案

答案 2 :(得分:0)

可以以递增的方式计算每个ai的系数。我相信给定n的一半系数需要计算,因为另一半将包含重复的元素。因此每个n将在表中包含n / 2个值。这种方法将导致n ^ 2运行时间。不知道这可以进一步改善。