具有给定条件的最长子序列

时间:2018-01-25 10:44:56

标签: arrays algorithm data-structures dynamic-programming

给定一个数组 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。 请注意,子序列以数组的第一个元素开头。

我认为这个问题可以通过动态编程解决,但我无法提出递归关系。

1 个答案:

答案 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]),该函数应在合理的时间内返回正确的答案。