假设我正在递归地(自上而下)解决一个动态编程问题。例如,最长公共子序列问题的递归解:
LCS(S,n,T,m)
{
if (n==0 || m==0) return 0;
if (S[n] == T[m]) result = 1 + LCS(S,n-1,T,m-1);
else result = max( LCS(S,n-1,T,m), LCS(S,n,T,m-1) );
return result;
}
通常在这样一个DP问题中,在某一点上,我们必须取一些表达式的最大值,代表我们可以做出的不同选择的返回值。在上面的例子中,我们有两个简单表达式的最大值,但在更糟的情况下,它可以是三个或四个涉及长函数调用的相当复杂的表达式的最大值。在这种情况下,我常常试图给这些复杂的表达式指定自己的变量名,以使代码更具可读性。在上面的情况下,这意味着我会写
LCS(S,n,T,m)
{
if (n==0 || m==0) return 0;
if (S[n] == T[m]) result = 1 + LCS(S,n-1,T,m-1);
else
a = LCS(S,n-1,T,m);
b = LCS(S, n, T, m-1);
result = max(a, b);
return result;
}
(在这种简化的情况下
a
和
b
不复杂,但在其他情况下,它们是复杂的,而且max函数可能有更多的参数,因此这确实有助于它更容易理解。)
我的问题:
这是个糟糕的主意吗?据我所知,我在调用堆栈的每一层添加一个变量,我认为这可能是浪费。但另一方面,在每一层都要计算临时变量
LCS(S,n,T,m)
不管怎样,(我想用C++来计算),据我所知,这两种方法之间的成本差别不大。
如果这是一个糟糕的想法,有没有更有效的方法来分解一个复杂的递归函数调用,使其更具可读性?