即:
请你帮他算算这个最大值是多少吧。
本题有多组测试数据。
输入的第一行包含一个正整数,表示数据组数。
接下来包含组数据,每组数据的格式如下:
第一行两个正整数,表示小苯的序列
的长度,以及需要恰好划分成的连续段个数。
第二行个整数
,表示序列
。
(保证同一个测试文件的所有测试数据中,的总和不超过
。)
对于每组测试数据:
输出一行一个整数,表示所求式子的最大值。
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]); } } }