----最大M子段和问题
给定由 n个整数(可能为负整数)组成的序列以及一个正整数 m,要求确定序列的 m个不相交子段,使这m个子段的总和达到最大,求出最大和。
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 ≤ i y ≤ 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. _
Each test case will begin with two integers m and n, followed by n integers S 1, S 2, S 3 … S n.
Process to the end of file.
Output the maximal summation described above in one line.
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
6
8
很明显,我们不能知道某一点是否该加入段中,加入到那一段中,不能用贪心写,那么只能用动态规划,看某点j是否需要加入i段中,或是新开一段作为新段的开头。
#include
#include
#include
using namespace std;
typedef long long ll;
const int M=1e6+10;
const int inf=0x3f3f3f3f;
int n,m,dp[M],f[M],s[M],ans;
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1; i<=m; i++)
scanf("%d",&f[i]);
memset(dp,0,sizeof(dp));
memset(s,0,sizeof(s));
for(int i=1; i<=n; i++)
{
ans=-inf;
for(int j=i; j<=m; j++)
{
dp[j]=max(dp[j-1]+f[j]/*f[j]属于第i段*/,s[j-1]+f[j]/*f[j]不属于第i段为新的段加上前i-1段,看是否较大*/);/*看该点是否为新段的开始*/
s[j-1]=ans;/*上一段(i-1)到j-1点的最大值*/
ans=max(dp[j],ans);/*在第i段第j点的最大值,为当前最大值*/
}
}
printf("%d\n",ans);
}
return 0;
}