我想找到一个正整数数组的最大权重子序列 - 问题是在最后的子序列中不允许相邻的成员。
提出了完全相同的问题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));
}
};
答案 0 :(得分:1)
但是你不明白什么?对我来说似乎很清楚:
i
的前缀的最大子序列,我们考虑两种可能性:最后一个元素是,还是不在最大子序列中(显然没有其他可能性)。另外:你需要记住实际的子序列;你需要避免多余的函数调用,因此要记忆。
为什么他将
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].
)
我认为这种方式比你在那里更容易理解。方法是等价的,我只是发现这个特殊问题更清楚,因为在这种情况下递归会使事情变得更难,并且伪代码可能更清晰。