即:
请你帮他算算这个最大值是多少吧。
本题有多组测试数据。
输入的第一行包含一个正整数,表示数据组数。
接下来包含组数据,每组数据的格式如下:
第一行两个正整数,表示小苯的序列
的长度,以及需要恰好划分成的连续段个数。
第二行个整数
,表示序列
。
(保证同一个测试文件的所有测试数据中,的总和不超过
。)
对于每组测试数据:
输出一行一个整数,表示所求式子的最大值。
2 5 4 1 3 2 4 3 5 1 1 3 2 4 -3
23 7
对于第一组测试数据,划分为:这四个区间最优,
,最大和为:
。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- > 0) {
int n = sc.nextInt();
int m = sc.nextInt();
long[] a = new long[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = sc.nextLong();
}
// 前缀和
long[] prefix = new long[n + 1];
for (int i = 1; i <= n; i++) {
prefix[i] = prefix[i - 1] + a[i];
}
// dp[i][j] 表示前 i 个数划分为 j 段的最大值
long[][] dp = new long[n + 1][m + 1];
for (int i = 0; i <= n; i++) {
Arrays.fill(dp[i], Long.MIN_VALUE / 2);
}
dp[0][0] = 0;
// 动态规划
for (int j = 1; j <= m; j++) {
int weight = (j % 2 == 1 ? 1 : 2);
// best[k] = max(dp[k][j-1] - prefix[k]*weight)
long best = Long.MIN_VALUE / 2;
for (int i = 1; i <= n; i++) {
// 先更新 best (相当于枚举k=i-1)
best = Math.max(best, dp[i - 1][j - 1] - prefix[i - 1] * weight);
// 再利用 best 转移到 dp[i][j]
dp[i][j] = prefix[i] * weight + best;
}
}
System.out.println(dp[n][m]);
}
}
}