【问题标题】:Maximum Weight Increasing Subsequence最大权重增加子序列
【发布时间】:2012-01-09 01:12:13
【问题描述】:

Longest Increasing Subsequence Problem 中,如果我们按权重更改长度,即每个元素的长度 Ai 如果我们将其更改为 Wi 则为 1 我们如何在 O(NlogN) 中做到这一点。

例如 对于 8 个元素的数组

Elements 1  2  3  4  1  2  3  4
Weights  10 20 30 40 15 15 15 50 

最大重量为 110。

我在维基百科上找到了 LIS 解决方案,但我无法修改它来解决这个问题。

【问题讨论】:

  • 用测试用例在 HackerRank 上解决这个问题 - www.hackerrank.com/challenges/subsequence-weighting

标签: algorithm dynamic-programming


【解决方案1】:

不过,我们使用f[i] 表示我们可以通过以E[i] 结尾的序列获得的最大值。

所以通常我们有for (int i = 1;i <= n;i++) f[i] = dp(i); 和最初的f[0] = 0;E[0] = -INF;

现在我们将在O(log(N)) 中计算f[i] 中的dp(i)

dp(i) 中,我们将找到所有0 <= j < i 的最大f[j]E[j] < E[i]。在这里我们可以维护一个Segment Tree

所以dp(i) = find_max(1,E[i]-1) + W[i](这需要O(log)),并且对于已经计算的每个f[i],update(E[i],f[i])

所以整个算法采用(O(NlogN))

提示:如果E[i] 的变化范围很大,则可以是Discretizationed。

【讨论】:

  • 什么是 dp[i] ?请问段树中将存储什么?谢谢。
  • @amahfouz dp(i) 只是一个计算 f[i] 值的函数。段树中,索引(或范围)为E的值,单槽更新值,查询一个范围内的最大值,典型的段树。
  • 感谢您的回复。
【解决方案2】:

这是 swift 中的纯递归实现:

// input is Array of (a,w), where a is element and w is weight

func lisw(input: [(Int, Int)], index:Int = 0, largestA:Int? = nil)->Int{
       guard index < input.count else { return 0 }

       let (a,w) = input[index]

       if a <= largestA {
          return lisw(input: input, index: index + 1, largestA: largestA)
       }

       let without_me = lisw(input: input, index: index + 1, largestA: largestA == nil ? a : largestA)
       let with_me = lisw(input: input, index: index + 1, largestA: a) + w

       return max(without_me,with_me)
}

随意添加记忆;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 2012-06-07
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    相关资源
    最近更新 更多