原题:
> Max Sum Plus Plus
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/32768 K (Java/Others)
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. ^_^
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.
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.
原题链接:
http://hdu.hustoj.com/showproblem.php?pid=1024
题意:这题大概的意思是,给出n个数的序列,然后在里面找出m段出来,使得这m段的和最大,每一段可以是一个数字组成,也可以是几个数字组成,但这几个数字必须连续的,上面的Ouput是这样得出来的:
第一个:1 3 1 2 3,m=1,n=3,在这三个数中取一段出来,使其和最大,最大的一段就是1,2,3这段,和为6
第二个:2 6 -1 4 -2 3 -2 3 m=2,n=6,在这六个数中取两段出来,4,-2,3为一段,最后的数字3为一段,这两段的和最大,为8.
java代码:
这里参考了另外一篇博客写的,另外一篇博客是用C语言写的,那里有更详细的图解
http://blog.sina.com.cn/s/blog_677a3eb30100jxqa.html
这篇博客为了节省内存,采用了连滚数组
import java.util.Scanner;
public class Main {
private static long[][] dp = new long[2][1000001];
private static long[] a = new long[1000001];
private static int n,m;
private static long maxNum; //上一行中j之前最大的那个数
private static long res ; //分成m段最大值,初始化long范围最小值
private static int index; //两行数组索引下标
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (input.hasNext()){
m = input.nextInt();
n = input.nextInt();
index = 1;
res = Long.MIN_VALUE;
/**
* dp[0][]和dp[1][]是相邻的两行,在处理数据中相互转换
*/
for(int i=1;i<=n;i++){
dp[0][i] = dp[1][i] = 0;
a[i] = input.nextInt();
}
for(int i=1;i<=m;i++){
dp[index][i] = dp[1 - index][i-1] + a[i];
maxNum = dp[1 - index][i-1];
for (int j=i+1;j<=n-m+i ;j++){
maxNum = Math.max(maxNum,dp[1-index][j-1]);
dp[index][j] = Math.max(dp[index][j-1],maxNum) + a[j];
}
index = 1 - index; //转换两行数据
}
index = 1 - index;
for (int j=m;j<=n;j++){
res = Math.max(dp[index][j],res);
}
System.out.println(res);
}
}
}