我试图找到一种算法来查找实数的数组K
的大小为L
的{{1}}个不相交的连续子集,这些子集最大化了元素的总和。
详细说明,X是一组N个正实数:
x
一个名为X={x[1],x[2],...x[N]} where x[j]>=0 for all j=1,...,N.
的长度为L的连续子集被定义为X的L个连续成员,从位置S[i]
开始到结束位置n[i]
:
n[i]+L-1
如果S[i] = {x[j] | j=n[i],n[i]+1,...,n[i]+L-1} = {x[n[i]],x[n[i]+1],...,x[n[i]+L-1]}.
,则其中两个此类子集S[i]
和S[j]
称为成对不相交(非重叠)。换句话说,他们不包含任何相同的X成员。
定义每个子集成员的总和:
|n[i]-n[j]|>=L
目标是找到长度为L的K个连续且不相交(非重叠)的子集SUM[i] = x[n[i]]+x[n[i]+1]+...+x[n[i]+L-1];
,以使S[1],S[2],...,S[K]
最大化。
答案 0 :(得分:2)
这是通过动态编程解决的。让M[i]
成为i
的第一个x
元素的最佳解决方案。然后:
M[i] = 0 for i < L
M[i] = max(M[i-1], M[i-L] + sum(x[i-L+1] + x[i-L+2] + ... + x[i]))
问题的解决方案是M[N]
。
编码时,您可以递增计算总和(或简单地预先计算所有总和),从而在空间和时间上导致O(N
)解决方案。
如果您必须准确找到K
个子集,则可以通过将M[i, k]
定义为第一个k
元素上i
个子集的最佳解决方案来扩展此范围。然后:
M[i, k] = 0 for i < k * L or k = 0.
M[i, k] = max(M[i-1, k], M[i-L, k-1] + sum(x[i-L+1] + ... + x[i])
问题的解决方案是M[N, K]
。
这是一个2d动态编程解决方案,具有O(NK
)的时间和空间复杂度(假设您使用与上面相同的技巧来避免重新计算总和)。