Problem Description:
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.
Given a consecutive number sequence S1, S2, S3, S4 ... Sx, ... Sn (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ Sx ≤ 32767). We define a function sum(i, j) = Si + ... + Sj (1 ≤ i ≤ j ≤ n).
Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i1, j1) + sum(i2, j2) + sum(i3, j3) + ... + sum(im, jm) maximal (ix ≤ iy ≤ jx or ix ≤ jy ≤ jx is not allowed).
But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(ix, jx)(1 ≤ x ≤ m) instead. ^_^
Given a consecutive number sequence S1, S2, S3, S4 ... Sx, ... Sn (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ Sx ≤ 32767). We define a function sum(i, j) = Si + ... + Sj (1 ≤ i ≤ j ≤ n).
Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i1, j1) + sum(i2, j2) + sum(i3, j3) + ... + sum(im, jm) maximal (ix ≤ iy ≤ jx or ix ≤ jy ≤ jx is not allowed).
But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(ix, jx)(1 ≤ x ≤ m) instead. ^_^
Input:
Each test case will begin with two integers m and n, followed by n integers S1, S2, S3 ... Sn.
Process to the end of file.
Process to the end of file.
Output:
Output the maximal summation described above in one line.
Sample Input:
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
Sample Output:
6
8
Hint
Huge input, scanf and dynamic programming is recommended.题意:有一个长度为n的序列,现在要被分成不交叉的m段序列(不用分完所有的元素),问怎样分才能使这m段序列的和最大,这道题不求这m段是什么,只用输出这个最大的值。
假设我们让数组a[j]表示输入的数组,DP[i][j]表示前j个数被分成i组的最大和(不用分完所有前j个元素),那么我们必须明白:第j个数可能被独立分成第i组,也可能加在第j-1个数的后面,成为第i组的元素(此时第i组元素只有第j个数),所以状态转移方程变为dp[j] = max(dp[j-1]+a[j], Max[j-1]+a[j]) (因为如果开二维数组内存过大,所以我们可以采用双重for循环形式进行计算最大值,此时只需要两个一维数组就可以了)。
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int N=1000010; const int INF=0x3f3f3f3f; int a[N], dp[N], Max[N]; ///dp[j]存放前j个数分组后的最大值,Max[j-1]存放上一组的最大值 int main () { int m, n, i, j, M; while (scanf("%d%d", &m, &n) != EOF) { for (i = 1; i <= n; i++) scanf("%d", &a[i]); memset(dp, 0, sizeof(dp)); memset(Max, 0, sizeof(Max)); for (i = 1; i <= m; i++) ///i代表组数,j代表元素个数 { M = -INF; ///每次多分一组都需要统计最大值 for (j = i; j <= n; j++) ///j从i开始是因为组数肯定要比元素个数少 { dp[j] = max(dp[j-1]+a[j], Max[j-1]+a[j]); ///dp[j-1]+a[j]代表a[j]连在a[j-1]后面成为第i组,但是该组只有a[j]一个元素,Max[j-1]+a[j]代表a[j]独立成组 Max[j-1] = M; ///先保存最大值,后计算这一组的最大值,则下次使用Max数组时就变成了上一组的最大值了 M = max(M, dp[j]); } } printf("%d ", M); } return 0; }