给定一个数组 A 具有 n 元素和整数 k 。我需要从数组的第一个元素开始找到最长的子序列,并且子序列的总权重≤k。
子序列的权重定义为选择子序列的连续元素的绝对差之和。
约束: -
1≤n≤10^ 5
0≤k≤50
0≤Ai≤50
示例: n = 4, k = 5, A = [1,2,50,6]
答案:最长的有效子序列 [1,2,6] ,长度 3 。 子序列的权重是| 1 - 2 | + | 2 - 6 | = 1 + 4 = 5。 请注意,子序列以数组的第一个元素开头。
我认为这个问题可以通过动态编程解决,但我无法提出递归关系。
答案 0 :(得分:0)
想象一下,您正在处理数组A,选择要包含在子序列中的值。在每个步骤中,您可以(a)包含当前值,或(b)不包括它。如果你记住这两个选项中的更好,那么应该可以使动态编程工作。
在伪代码中,你的函数看起来像这样:
int longest_subseq(ix, available_weight, last_val):
# Parameters:
# ix = an index into array A (assumed to have global scope)
# available_weight = the remaining weight avaiable for the subsequence
# starting at ix
# last_val = the last value in the subsequence from A[0] through A[ix-1]
# When first called, create a DP array of 10^5 × 51 × 51 elements
# (This will use about 1GB of memory, which I assume is OK)
if DP is undefined:
DP = new array(100001, 51, 51)
initialize every element of DP to -1
# Return memoized value if available
v = DP[ix, available_weight, last_val]
if v >= 0:
return v
# Check for end conditions
if ix == n or available_weight == 0:
return 0
# Otherwise you have two options; either include A[ix] in the
# subsequence, or don't include it
len0 = longest_subseq(ix+1, available_weight, last_val)
if abs(A[ix] - last_val) > available_weight:
DP[ix, available_weight, last_val] = len0
return len0
len1 = 1 + longest_subseq(ix+1, available_weight-abs(A[ix]-last_val), A[ix])
if len0 > len(1):
DP[ix, available_weight, last_val] = len0
return len0
else:
DP[ix, available_weight, last_val] = len1
return len1
如果您再调用longest_subseq(0, k, A[0])
,该函数应在合理的时间内返回正确的答案。