找到正整数数组的最大权重子序列?

时间:2010-05-23 11:33:09

标签: c++ algorithm recursion

我想找到一个正整数数组的最大权重子序列 - 问题是在最后的子序列中不允许相邻的成员。

提出了完全相同的问题here,MarkusQ给出了一个递归解决方案:

function Max_route(A)
if A's length = 1 
    A[0]
  else
    maximum of
      A[0]+Max_route(A[2...])
      Max_route[1...]

他提供了一个解释,但任何人都可以帮助我理解他是如何扩展这个功能的吗?具体是什么意思

f[] :- [],0
f [x]     :- [x],x
f [a,b]   :- if a > b then [a],a else [b],b
f [a,b,t] :- 
    ft = f t
    fbt = f [b|t]
    if a + ft.sum > fbt.sum
        [a|ft.path],a+ft.sum
    else
      fbt

为什么他将f[]扩展为[],0?他的解决方案如何考虑非相邻成员?

我有一些基于这个算法的C ++代码,如果有人想看到它我可以发布,但我不能为我的生活找到它的工作原理。

==========对于任何有兴趣的人 - C ++代码==============

我应该补充一点,整数数组将被视为循环列表,因此包含第一个元素的任何序列都不能包含最后一个。

int memo[55][55];

int solve(int s, int e)
{
    if( s>e ) return 0;
    int &ret=memo[s][e];
    if(ret!=-1)
    {
        return ret;
    }
    ret=max(solve(s+1,e), solve(s+2,e)+a[s]);
    return ret;
}

class Sequence
{
    public:
    int maxSequence(vector <int> s)
    {
            memset(memo,-1);
            int n = s.size();
            for(int i=0; i<n; i++)
                a[i]=s[i];
            return max(solve(0,n-2),solve(1,n-1));
        }
};

2 个答案:

答案 0 :(得分:1)

但是你不明白什么?对我来说似乎很清楚:

  • 我们将为我们给定序列的每个前缀构建最大子序列
  • 计算长度为i的前缀的最大子序列,我们考虑两种可能性:最后一个元素是,还是不在最大子序列中(显然没有其他可能性)。
  • 如果它在那里,我们考虑最后一个元素的值,加上前缀的两个元素的最大子序列的值更短(因为在这种情况下,我们知道最后一个元素不能出现在最大子序列中,因为相邻元素规则)
  • 如果不是,我们将前缀的最大总和的值减去一个元素(如果前缀的最后一个元素不在最大子序列中,则最大子序列对于此和前一个前缀必须相等)< / LI>
  • 我们比较并取两个
  • 的最大值

另外:你需要记住实际的子序列;你需要避免多余的函数调用,因此要记忆。

  

为什么他将f[]扩展为[],0

因为返回值中的第一个值表示当前最大子序列,第二个值是其值。空序列的最大子序列为空,其值为零。

答案 1 :(得分:1)

我真的不明白那个伪代码,所以发布C ++代码如果这没用,我会尝试改进它。

  

我想找到一个正整数数组的最大权重子序列 - 问题是在最后的子序列中不允许相邻的成员。

a成为您积极的一组。让f[i] = value of the maximum weight subsequence of the sequence a[0..i]

我们有:

f[0] = a[0]因为如果只有一个元素,我们必须接受它 f[1] = max(a[0], a[1])因为你没有相邻的元素限制,所以如果你有两个元素,你只能选择其中一个元素。采取最大的一个是有意义的。

现在,通常你有:

f[i > 1] = max(
           f[i - 2] + a[i] <= add a[i] to the largest subsequence of the sequence a[0..i - 2]. We cannot take a[0..i - 1] because otherwise we risk adding an adjacent element.
           f[i - 1] <= don't add the current element to the maximum of a[0..i - 2], instead take the maximum of a[0..i - 1], to which we cannot add a[i].
              )

我认为这种方式比你在那里更容易理解。方法是等价的,我只是发现这个特殊问题更清楚,因为在这种情况下递归会使事情变得更难,并且伪代码可能更清晰。