找到数组中n个元素的最大总和,使得不超过k个元素相邻

时间:2013-02-07 06:51:16

标签: algorithm dynamic-programming

几乎与此相同: find maximum sum of elements in an array such that not more than k elements are adjacent

除了我们可以选择的n个元素的限制。如何修改DP算法使其适用于此?

2 个答案:

答案 0 :(得分:4)

添加DP功能的新维度: f[i, j, l] - 第一个 i 元素的最大总和,如果在此总和中使用 j 总元素和最后l个元素

答案 1 :(得分:2)

嗯,让我说得更清楚。

问题:找到数组中n个元素的最大总和,使得不超过K个元素相邻

let int f [i] [j] [k] 表示使用j个总元素和最后k个元素的前i个元素的最大和。让 bool g [i] [j] [k] 表示是否可以获得某种组合。例如。 g [1] [1] [2]是假的。这很重要,因为没有限制,f可能会产生不可能的答案。

最初,memset f和g为全零,并设置g [0] [0] [0]为真。我们可以使用前向递归来解决这个DP问题。显然,每次遇到一个数字时,你都有两个选择:选择它,或者选择它。 thay给出了递推公式:

f[i][j][k] can infer f[i+1][j+1][k+1], or
f[i][j][k] can infer f[i+1][j][0]

所以,伪代码可以如下:

memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
g[0][0][0]=true;
for (int i=0;i<array.size();i++)
    for (int j=0;j<=n;j++)
        for (int k=0;k<=K;k++) if (g[i][j][k]) {
            f[i+1][j][0]=max(f[i+1][j][0],f[i][j][k]);
            f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]+array[i]);
            g[i+1][j][0]=true;
            g[i+1][j+1][k+1]=true;
        }

,最终结果将是:

ans=0;
for (i=0;i<=K;i++)
    ans=max(ans,f[array.size()][n][i]);
return ans;

上面给出了完全j个元素。如果你想获得最多j个元素,你可以用这种方式改变它:

ans=0;
for (i=0;i<=n;i++)
    for (j=0;j<=K;j++)
        ans=max(ans,f[array.size()][i][j]);
return ans;