动态规划的应用

时间:2014-08-05 19:02:22

标签: algorithm dynamic-programming

我正准备进行软件开发人员访谈,并尝试了解如何应用动态编程。我知道问题必须符合两个标准 - 具有最佳子结构和重叠子问题。给出一个你有一个函数的例子,f(L)取一个整数列表L并将它映射到另一个整数(例如,f([17,1,5,12] = 35)你将如何应用动态编程找到最大值?

实施例

L = [17, 5, 2, 12, 9]

您可以使用f()的各种组合:

f([17]) + f([5]) + f([2, 12, 19])
f([17]) + f([5, 2]) + f([12, 19])

我通过计算列表中每个元素的f()来接近它,例如f([17])。然后每两个元素,如f([17,5]),然后每三个元素,f([5,2,12]),等等。然后我将这些值映射到哈希表。接下来,我尝试了f()的所有组合来找到最大值。我认为这种做法并不优雅,有点尴尬。关于如何处理的任何想法?

2 个答案:

答案 0 :(得分:3)

动态编程的一种典型方法是创建一个递归遍历子问题的所有有效排列的函数,以便给出最终答案,并在进行时保存子问题的所有答案(称为 memoization ),因为那些subanswers可能是非常可重用的。在示例问题的伪代码中:

function F(some_list) {
    ....
}

M = [[]]
L = [17, 5, 2, 12, 9]

function maximize(start, end) {
    // If we have already calculated the highest value
    // for the given slice, why do it again?
    if (M[start][end] != NULL) {
        return M[start][end]
    }

    // The function f applied to the whole slice we are
    // examining is also a viable solution, so we start
    // our hunt there
    max = F(L.slice(start, end))

    // If we are at an end node (that is, we can't
    // divide the problem into smaller pieces) we return
    // and save the value we just calculated
    if (end - start == 1) {
        M[start][end] = max
        return max
    }

    // Let's look at all possible ways we can split the
    // slice we are currently examining
    for (split in range(start + 1, end - 1)) {
        // Let's examine booth parts of the slice and see if
        // the sum of those solutions are better than our
        // previous best solution
        temp_max = maximize(start, split) + maximize(split, end)

        if (temp_max > max) {
            max = temp_max
        }
    }

    // We have examined all possible ways in which we can
    // slice and dice our slice, and found the best
    // solution. Yay! Let's save it for future reference.
    M[start][end] = max
    return max
}

// Examine the whole list
the_great_maximum_value = maximize(0, L.length)

答案 1 :(得分:1)

这是一种可行的方法:

1)让我们将dp[pos]定义为可以通过以某种方式分割列表的第一个pos元素而获得的最大值(无论如何)。

2)基本情况:dp[0] = 0。这是空前缀的情况。

3)pos > 0
 dp[pos] = max(dp[prev_pos] + f(L[prev_pos + 1], L[prev_pos + 2], ..., L[pos]))0 <= prev_pos < pos

4)答案为dp[length(L)]

时间复杂度为O(n^2 * time_to_comptute_f)(因为我们遍历列表中的所有位置以及每个位置检查O(n)以前的位置,每次都计算f

空间复杂度为O(n)