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

Posted

技术标签:

【中文标题】求数组中 n 个元素的最大和,使得相邻的元素不超过 k 个【英文标题】:find maximum sum of n elements in an array such that not more than k elements are adjacent 【发布时间】:2013-02-07 06:51:15 【问题描述】:

几乎和这个一样: find maximum sum of elements in an array such that not more than k elements are adjacent

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

您好,我在计算递推公式时遇到了麻烦,您能给出递推公式吗?谢谢 例如,P(v,i) = P(v-1,i-1) + C(v) if i > 0 P(v,0) = max(P(v-1,i) for i = 0..min(k, v)) P(0,0) = 0 是我链接到的另一篇文章中的递归公式。你能提供 f[i, j, l] 函数的公式吗?【参考方案2】:

好吧,让我把它说得更清楚。

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

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

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

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;

【讨论】:

@WilliamRookwood 首先,我认为我在原始代码中犯了一个小错误。我很快就会编辑我的帖子。 @WilliamRookwood 我回答你的问题了吗?您需要更多帮助吗?

以上是关于求数组中 n 个元素的最大和,使得相邻的元素不超过 k 个的主要内容,如果未能解决你的问题,请参考以下文章

一维数组求最大子数组的和(首位相邻32位)

给定一个数组,求如果排序后,相邻两个元素的最大差值,要求时间复杂度为O(N)

Leetcode练习(Python):数组类:第75题:给定一个包含红色白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色白色蓝色顺序排列。

数组中 N 个元素的绝对差的最大和

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和。要求时间复杂度为O(n)(解决)

最大子数组之和首位相邻32位版