题目链接:Maximum Subarray
解法(动态规划):
定义f[i][j]:前i个数中有j个数+x,并以i结尾的子数组的最大元素和
1、j = 0:
f[i][0] = max(v - x, v - x + f[i-1][0])
2、j > 0:
f[i][j] = v + x + max(0, f[i-1][j-1])
// 当前元素+x,留给前面元素的x个数只剩 j - 1
若 j <= i - 1 则 f[i][j]还需要与 v - x + max(0, f[i-1][j])进行比较
// 当前元素-x,则留给前面元素的x个数为 j, 如果前面元素的个数 <= j,则为非法情况不考虑
代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <stack>
#include <list>
#include <bitset>
#include <utility>
#include <deque>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <functional>
#include <cstdlib>
#include <string.h>
#include <bitset>
#include <string_view>
#include <thread>
#include <future>
#define ll long long
#define ull unsigned long long
#define srt short
template<class _Tp>
struct GT {
constexpr bool operator()(const _Tp& a, const _Tp& b) const { return a > b; }
};
template<class _Tp>
struct LS {
constexpr bool operator()(const _Tp& a, const _Tp& b) const { return a < b; }
};
const int N = 200010, M = 21;
ll f[N][M];
int t, n, k, x;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &n, &k, &x);
ll ans = 0, v;
for (int i = 1; i <= n; i++) {
scanf("%lld", &v);
// 这两个参数用于确定当前位置j的合法范围
int tot = std::min(i, k);
int restCnt = n - i;
for (int j = std::max(0, k - restCnt); j <= tot; j++) {
if (!j) f[i][0] = std::max(v - x, v - x + f[i - 1][0]);
else {
f[i][j] = v + x + std::max(0ll, f[i - 1][j - 1]);
if (j <= i - 1) f[i][j] = std::max(f[i][j], v - x + std::max(0ll, f[i - 1][j]));
}
ans = std::max(ans, f[i][j]);
}
}
printf("%lld\n", ans);
}
return 0;
}