Description
N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。
例如:-2 11 -4 13 -5 6 -2,分为2段,11 -4 13一段,6一段,和为26。
题解
首先,题目的意思有点绕,这里的答案其实是可以选 1..m 个子段的最优解。
那么,我们定义
f[i][j]
表示第
i
位,当前总共选了
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 5006
#define LL long long
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0,p=1;
while(ch!='-'&&!(ch>='0'&&ch<='9'))ch=nc();
if(ch=='-')p=-1,ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum*p;
}
int n,m,a[maxn];
LL ans,sum[maxn],g[maxn],f[2][maxn];
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
n=_read();m=_read();
for(int i=1;i<=n;i++)a[i]=_read();
memset(f,192,sizeof(f));memset(g,192,sizeof(g));
g[0]=0;
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--){
f[i&1][j]=max(g[j-1]+a[i],f[1-(i&1)][j]+a[i]);
g[j]=max(g[j],f[i&1][j]);
ans=max(ans,f[i&1][j]);
}
printf("%lld",ans);
return 0;
}