UVa 10134:更聪明吗? (动态编程和最长增长子序列)

时间:2011-04-26 19:49:25

标签: java dynamic-programming

private void findLDS() {
    Integer[] array = Arrays.copyOf(elephants.iq, elephants.iq.length);
    Hashtable<Integer, Integer> eq = elephants.elephantiqs;

    Integer[] lds = new Integer[array.length];
    Integer[] prev= new Integer[array.length];
    lds[0] = 0;
    prev[0] = 0;

    int maxlds = 1, ending=0;

    for(int i = 0; i < array.length; ++i) {
        lds[i] = 1;
        prev[i] = -1;

        for (int j = i; j >= 0; --j) {
            if(lds[j] + 1 > lds[i] && array[j] > array[i] && eq.get(array[j]) < eq.get(array[i])) {
                lds[i] = lds[j]+1;
                prev[i] = j;
            }
        }
        if(lds[i] > maxlds) {
            ending = i;
            maxlds = lds[i];
        }
    }
    System.out.println(maxlds);
    for(int i = ending; i >= 0; --i) {
        if(prev[i] != -1) {
            System.out.println(eq.get(array[prev[i]])); 
        }

    }

我已将此算法基于此SO question。此代码试图找到最长的递减子序列而不是增加。 array []按降序排序,我也有一个哈希表,大象IQ作为权重的关键。

我很难理解DP,我需要一些帮助。

除了跟踪prev []中选择的序列之外,我的算法似乎工作得很好,因为它总是错过一个元素。有谁知道怎么做?

1 个答案:

答案 0 :(得分:2)

接近这个的几种方法:

  1. 按重量顺序排序,然后找到增长最长的子序列。
  2. 按IQ降序排序,然后找到权重最长的增加子序列。
  3. 和4.只是(1)和(2),切换词“增加”和“减少”
  4. 如果您不了解DP增长最长的子序列O(N ^ 2),那基本上就是这样:

    1. 由于列表必须严格增加/减少,你可以事先消除一些大象,使这个集合独一无二。
    2. 创建一个数组,我将其称为llis代表“最长增加子序列”,长度 N ,现在有大象的数量。创建另一个名为last的数组,其长度相同。我将假设已排序的大象列表在问题陈述中称为array
    3. 假设您已经按降序对大象进行了分类,您将需要找到智商最长的增长子序列。
    4. 告诉自己数组llis中索引 n 的元素(这是一个不同的“n”)&lt; N 将是array的子数组从索引0到 n 的最长增长子序列的长度,包括端点。另请说,索引 n next数组中的元素将是array中增长最长的子序列中的下一个索引。
    5. 因此,在0到 N - 1 (包括整个数组)的“子阵列”中找到最长的增加子序列的长度,只需要找到<在DP计算之后,数组llis中的强> N - 1 元素,找到实际的子序列将简化为遵循next数组中的索引。
    6. 既然您知道自己在寻找什么,那么您可以继续使用算法。在数组中的索引 n 时,您如何知道增长最长的子序列是什么?好吧,如果你已经计算了每个 k 的子序列中最长增加子序列的长度和子序列中的最后一个值。 n ,如果大象的智商 n,您可以尝试将指数 n 的大象添加到 k 结尾的最长增长子序列高于 k 时大象的智商。在这种情况下,以大象 n 结束的最长增长子序列的长度将为llis[k] + 1。 (另外,请记住将next[k]设置为 n ,因为增加子序列中的下一个大象将是 n 中的大象。)
    7. 我们在经过 n 之前的所有 k 之后找到了llis[n] = max(llis[n], llis[k] + 1)的DP关系。只需按正确的顺序处理 n (线性),您就应该得到正确的结果。
    8. 程序/警告:1)按0到 N - 1 的顺序处理 n 。 2)对于每个 n ,按 n - 1 顺序处理 k 为0,因为您希望最小化 k 你选择的。 3)完成处理后,请务必在数组llis中找到最大号以获得最终结果。
    9. 由于这被标记为家庭作业,我不会明确说明如何修改它以找到最长的减少子序列,但我希望我的解释有助于您理解DP。如果您选择使用它,应该很容易找到自己的减少版本。 (请注意,使用增加版本可以解决此问题,如方法1或2中所述。)
相关问题