/* 经典的动态规划优化的问题。设f(i, j)表示前i个数划分成j段,且包括第i个数的最大m子段和,那么有dp方程: f(i, j) = max { f(i - 1, j) + v[i], max {f(k, j - 1) + v[i]}(k = j - 1 ... i - 1) } 可以引入一个辅助数组来优化转移。设g(i, j)表示前i个数划分成j段的最大子段和(注意第i个数未必在j段里面),那么递推关系如下: g(i, j) = max{g(i - 1, j), f(i, j)}, 分是否加入第i个数来转移 这样f的递推关系就变成: f(i, j) = max{f(i - 1, j), g(i - 1, j - 1)} + v[i],转移变成了O(1) 这样最后的结果就是g[n][m],通过引入辅助数组巧妙的优化了转移。实现的时候可以用一维数组,速度很快 g[i][j]要么和g[i-1][j]相等,要么和f[i][j]相等 f[i][j]-a[i]要么和g[i-1][j-1]相等,要么和f[i-1][j]相等 转成一维数组 到第i行时:f[j]=max{ f[j],g[j-1] }+a[i] g[j]=max{ g[j],f[j] }; */ #include<iostream> using namespace std; int n,m; const int N=1000001; const int Min=-99999999; int F[N],G[N]; int a[N]; int Max_num(int a,int b) { if(a>b) return a; else return b; } int Min_num(int a,int b) { if(a<b) return a; else return b; } int main() { int i,j; while(scanf("%d%d",&m,&n)!=EOF && n && m) { for(i=1;i<=n;i++) { F[i]=Min; G[i]=Min; cin>>a[i]; } F[1]=a[1]; G[1]=a[1]; for(i=2;i<=n;i++) { int t=Min_num(i,m); for(j=1;j<=t;j++) { F[j]=Max_num(F[j]+a[i],G[j-1]+a[i]); G[j-1]=Max_num(G[j-1],F[j-1]); } G[j-1]=Max_num(G[j-1],F[j-1]); } cout<<G[m]<<endl; } return 0; }