我有这个问题,给定一个正数组,我必须找到元素的最大总和,这样就不会选择两个相邻的元素。最大值必须小于某个给定的K.我试着考虑没有k的类似问题的界限,但到目前为止我都失败了。我对后一个问题有以下dp-ish soln
int sum1,sum2 = 0;
int sum = sum1 = a[0];
for(int i=1; i<n; i++)
{
sum = max(sum2 + a[i], sum1);
sum2 = sum1;
sum1 = sum;
}
有人可以给我一些关于如何处理我目前问题的提示吗?
答案 0 :(得分:4)
我能想到的最好的是O(n * K)dp:
int sums[n][K+1] = {{0}};
int i, j;
for(j = a[0]; j <= K; ++j) {
sums[0][j] = a[0];
}
if (a[1] > a[0]) {
for(j = a[0]; j < a[1]; ++j) {
sums[1][j] = a[0];
}
for(j = a[1]; j <= K; ++j) {
sums[1][j] = a[1];
}
} else {
for(j = a[1]; j < a[0]; ++j) {
sums[1][j] = a[1];
}
for(j = a[0]; j <= K; ++j) {
sums[1][j] = a[0];
}
}
for(i = 2; i < n; ++i) {
for(j = 0; j <= K && j < a[i]; ++j) {
sums[i][j] = max(sums[i-1][j],sums[i-2][j]);
}
for(j = a[i]; j <= K; ++j) {
sums[i][j] = max(sums[i-1][j],a[i] + sums[i-2][j-a[i]]);
}
}
sums[i][j]
包含a[0..i]
不超过j
的非相邻元素的最大总和。最后解决方案是sums[n-1][K]
。
答案 1 :(得分:0)
答案 2 :(得分:0)
第一个想法:蛮力
迭代所有合法的索引组合并动态构建总和。
当你克服K时停止一个序列。
保持序列,直到找到一个更大的序列,它仍然小于K
第二个想法:也许人们可以强制分裂并征服它......
答案 3 :(得分:0)
以下是没有“k”约束的问题的解决方案,您将其作为第一步执行:https://stackoverflow.com/a/13022021/1110808
在我看来,上述解决方案可以通过简单地修改以下for循环中的if条件来容易地扩展为具有k约束,以包括约束:possibleMax&lt; ķ
// Subproblem solutions, DP
for (int i = start; i <= end; i++) {
int possibleMaxSub1 = maxSum(a, i + 2, end);
int possibleMaxSub2 = maxSum(a, start, i - 2);
int possibleMax = possibleMaxSub1 + possibleMaxSub2 + a[i];
/*
if (possibleMax > maxSum) {
maxSum = possibleMax;
}
*/
if (possibleMax > maxSum && possibleMax < k) {
maxSum = possibleMax;
}
}
如原始链接中所述,可以通过添加记忆来改进此方法,以便不重新计算重复子问题的解决方案。或者可以通过使用自下而上的动态编程方法来改进(当前方法是递归自顶向下方法)
您可以在此处参考自下而上的方法:https://stackoverflow.com/a/4487594/1110808