#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N];
int dp[3][N];
int n,m;
//dp[i][j]表示前j个数字分成i段的最大值;
//经过推导发现,dp的第i行只受到了i-1行的影响;
//所以我们可以进行空间的优化
//dp[i][j]=max(dp[i-1][k]+a[j],dp[i][j-1]+a[j]);--> i=<k<j;因为可能k和j之间可能有负数,所以可以不选;
//时间优化:我们用一个变量res,每次储存前[i,j)个字母的最大值来更新前j个字母;
int main()
{
while(~scanf("%d%d",&m,&n)){
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
memset(dp,0,sizeof dp);
int e=1;
int res=-99999999;
for(int i=1;i<=m;i++){
res=-9999999;//表示前j个字母最大值
for(int j=i;j<=n;j++){
dp[e][j]=max(dp[1-e][j-1]+a[j],dp[e][j-1]+a[j]);//
dp[1-e][j-1]=res;//更新得到的前【j-1】的最大值,并放到上一行;
res=max(res,dp[e][j]);//更新前j个字母最大值;
}
//for(int j=1;j<=n;j++) cout<<dp[1-e][j]<<" ";
//cout<<endl;
}
cout<<res<<endl;
}
return 0;
}
第二份代码
原理相同,不过这次每次的更新直接在本行执行
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N];
int dp[3][N];
int n,m;
//dp[i][j]表示前j个数字分成i段的最大值;
//经过推导发现,dp的第i行只受到了i-1行的影响;
//所以我们可以进行空间的优化
//dp[i][j]=max(dp[i-1][k]+a[j],dp[i][j-1]+a[j]);--> i=<k<j;因为可能k和j之间可能有负数,所以可以不选;
//时间优化:我们用一个变量,每次储存前j-1字母的最大值来更新前j个字母;
int main()
{
while(~scanf("%d%d",&m,&n)){
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
memset(dp,0,sizeof dp);
int e=1;
int res=-99999999;
for(int i=1;i<=m;i++){
res=-9999999;
e=1-e;
//dp[e][i]=dp[1-e][i-1]+a[i];
for(int j=i;j<=n;j++){
if(j==i){
dp[e][j]=dp[1-e][j-1]+a[j];
res=max(res,dp[e][j]);
continue;
}
else{
dp[e][j]=max(dp[1-e][j-1]+a[j],dp[e][j-1]+a[j]);//
}
dp[e][j-1]=res;//更新【j-1】的最大值,并放到上一行;
res=max(res,dp[e][j]);
}
dp[e][n]=res;
//for(int j=1;j<=n;j++) cout<<dp[e][j]<<" ";
//cout<<endl;
}
cout<<res<<endl;
}
return 0;
}