递推填表,填出来是个平行四边形;
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e6+5;
const int inf=0x3f3f3f3f;
LL f[N],last[N];
///f[i] 记录当前轮(当前段数k)以第i个数结尾的 最大k段和;
///last[i] 记录上一轮前i个f 的最大值;
///f[i][j]=max(f[i][j-1]+a[j],f[i-1][t]+a[j]); i-1<=t<=j-1;
///最少一个数一个段,t>=i-1;
int a[N];
LL read()
{
LL x=0,t=1;
char ch=getchar();
while(!isdigit(ch)){ if(ch=='-')t=-1; ch=getchar(); }
while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
return x*t;
}
int main()
{
int n,m;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(int i=1;i<=n;i++)
a[i]=read();
memset(f,0,sizeof(f) );
memset(last,0,sizeof(last) );
f[0]=-inf;
///最大子段和要求至少选一个物品,f[0]没有物品可选,初始化-inf;
///初始化时,last的值记录i-1=0的最大值,段数为0,因此last=0;
///f记录段数0的最大值,f=0;
LL maxn;
for(int i=1;i<=m;i++)
{
maxn=-inf;
for(int j=i;j<=n;j++)
{
f[j]=max(f[j-1],last[j-1])+a[j];
last[j-1]=maxn;
maxn=max(maxn,f[j]);
}
}
printf("%lld
",maxn);
}
return 0;
}
错点:
f[i]是以第i个数为结尾的最优解,所以到第m轮的时候,ans=max(f[k],ans), m<=k<=n;