题目:http://acm.hdu.edu.cn/showproblem.php?pid=1024
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 S 1, S 2, S 3, S 4 ... S x, ... S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + ... + S j (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(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + ... + sum(i m, j m) maximal (i x ≤ iy ≤ j x or i x ≤ j y ≤ j x 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(i x, j x)(1 ≤ x ≤ m) instead. ^_^
Input
Each test case will begin with two integers m and n, followed by n integers S 1, S2, S 3 ... S n.
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.
分析:求m个不相交子串的和最大。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define INF 0x7f7f7f7f
#define maxn 1000010
using namespace std;
int dp[maxn];
int maxm[maxn];//保存前边dp的最大值。
int s[maxn];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n) != EOF)
{
for(int i = 1;i <= n;i ++)
{
scanf("%d",&s[i]);
dp[i] = 0;
maxm[i] = 0;
}
int maxnn;
for(int i = 1;i <= m;i ++)
{
maxnn = -INF;
for(int j = i;j <= n;j ++)
{
dp[j] = max(dp[j-1]+s[j],maxm[j-1] + s[j]);
maxm[j - 1] = maxnn;
maxnn = max(maxnn,dp[j]);
}
}
printf("%d\n",maxnn);
}
return 0;
}
/*
状态:dp[i][j]表示q前j个数字分成i组时的和的最大值。
决策:第j个数字放在前一组还是自己成为一个新的组。
如果自己成为一个新的组就需要求出前边的i-1组的最大值。
如果划分为第i组的话就直接加到第j-1个数后边。
状态转移方程:dp[i][j]=max(dp[i][j-1]+s[i],max(dp[i-1][k])+s[i]);
优化:因为求max(dp[i-1][k])就相当于求前边的所有dp中前边的
j-1个数组成的i-1组的最大值,所以就要求出这前边的最大值。
因此我们用maxm[]来保存下这个值。不断的求出每一组的最大值。
*/