Max Sum Plus Plus
- 题目大意
之前有个问题是让你求n个数的最大子段和,现在这个问题是让你求n个数的m段最大子段和…..
- 题解
比之前那个问题更加复杂了,可以看到一段变成了m段,不能再像之前那样直接记录结果了。因为现在是分成了m段,所以我们增加一维方便定义状态:
我们用 d[i][j]表示分成i段,以j结尾的最大子段和。于是我们有转移方程
d[i][j]=max(d[i][j-1], 分成i-1段 到j-1时的解 )+a[j]
注意这里黑体的部分是分成i段,到j-1时的解而不是d[i-1][j-1]。所以我们用另外一个数组来记录解,我这里用的ans,递推方法与max sum如出一辙,这里就不说了。
- 代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[1000005],m,n,d[2][1000005],ans[2][1000005];
int main()
{
while (scanf("%d%d",&m,&n)!=EOF)
{
memset(a,0,sizeof(a));
memset(d,0,sizeof(d));
memset(ans,0,sizeof(ans));
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++)
{
if (i==j)
{
d[i%2][j]=d[(i-1)%2][j-1]+a[j];
ans[i%2][j]=d[i%2][j];
}
if (j>i)
{
d[i%2][j]=max(d[i%2][j-1],ans[(i-1)%2][j-1])+a[j];
ans[i%2][j]=max(ans[i%2][j-1],d[i%2][j]);
}
}
printf("%d\n",ans[m%2][n]);
}
return 0;
}