题目:从给定的一个长度为n的数组中,找出3个互不重叠的长度为k的子数组,使这3个数组的和最大。若有多组解,取最小下标的那组解。
思路:动归解决。
先以k个和把元素数组变成元素和数组A。
用一个3*n的二维数组DP存数据,存的是有row个子数组的时候,每个位置之前所有子数组的最大的和。
状态转移方程是:DP[i][j] = max{ DP[i][j - 1] , DP[i - 1][j - k] + A[j] }
找最小下标的办法是,从第三行开始到第一行,找存着最大数的最小下标即可,注意第二行第一行的下标上限是高一行的最小下标减去k。
题目较简单,思路实现起来有点复杂。
int max(int a, int b) {
if (a > b) return a;
else return b;
}
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
int l = nums.size() - k + 1;
int sums[20000];
for (int i = 0; i < l; ++i) sums[i] = 0;
for (int i = 0; i < l; ++i)
for (int j = 0; j < k; ++j)
sums[i] += nums[i + j];
int dp[3][20000];
for (int i = 0; i < 3; ++i)
for (int j = 0; j < l; ++j)
dp[i][j] = 0;
// dp[i][j] = maximun sum of previous j sums of number i
// 0
dp[0][0] = sums[0];
for (int i = 1; i < l; ++i) dp[0][i] = max(dp[0][i - 1], sums[i]);
// 1
dp[1][k] = sums[0] + sums[k];
for (int i = 1 + k; i < l; ++i) dp[1][i] = max(dp[1][i - 1], sums[i] + dp[0][i - k]);
// 2
dp[2][k + k] = sums[0] + sums[k] + sums[k + k];
for (int i = 1 + k + k; i < l; ++i) dp[2][i] = max(dp[2][i - 1], sums[i] + dp[1][i - k]);
vector<int> result(3);
int max, pos;
int limit = l;
for (int i = 2; i >= 0; --i) {
max = pos = 0;
for (int j = 0; j < limit; ++j) {
if (max < dp[i][j]) {
max = dp[i][j];
pos = j;
}
}
result[i] = pos;
limit = pos - k + 1;
}
return result;
}
};