首页 > 试题广场 >

小苯的序列分割1.0

[编程题]小苯的序列分割1.0
  • 热度指数:360 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小苯有一个长度为 n 的序列 a,他希望你能将 a 划分为恰好 m 个非空的连续段,并将其中每一段中的数字求和,组成一个长度恰好 m 的新序列 b。接着,最大化以下式子:

b_1+b_2 \times 2 + b_3 + b_4 \times 2...
即:b 中奇数位置的数字之和,加上偶数位置的数字之和 \times 2

请你帮他算算这个最大值是多少吧。

输入描述:
本题有多组测试数据。
输入的第一行包含一个正整数 T\ (1 \leq T \leq 100),表示数据组数。
接下来包含 T 组数据,每组数据的格式如下:
第一行两个正整数 n,m\ (1 \leq m \leq n \leq 3000),表示小苯的序列 a 的长度,以及需要恰好划分成的连续段个数。
第二行 n 个整数 a_i\ (-10^9 \leq a_i \leq 10^9),表示序列 a
(保证同一个测试文件的所有测试数据中,n 的总和不超过 3000。)


输出描述:
对于每组测试数据:
输出一行一个整数,表示所求式子的最大值。
示例1

输入

2
5 4
1 3 2 4 3
5 1
1 3 2 4 -3

输出

23
7

说明

对于第一组测试数据,划分为:

[1,1], [2,2], [3,3], [4,5] 这四个区间最优,b=\{1,3,2,7\},最大和为:1+3 \times 2 + 2 + 7 \times 2=23
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]);
        }
    }
}

发表于 2025-09-03 09:59:19 回复(0)