感觉这题很不错,思路如下,dp [ i ] [ j ]表示前j个数,分成i个子段所得到的最大子段和,其中包括j(为什么呢,自己举个例子就能理解了)。最终结果就是dp[ m ] [ n ],状态转移方程为dp [ i ] [ j ]=max ( dp[i ] [j-1 ], dp [ i-1 ] [ t ] ) ( 0 < t < j ) 有题目知 n,m最大为1000,000,那么二维数组肯定开不下。
所以运用一维滚动数组,状态转移方程:用pre表示 i-1 行,dp表示 i 行 ,dp[ j ]=max{ dp[ j-1 ] ,pre[ j-1 ] }+a[ j ];
代码如下:
#include<iostream>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define N 1000005
#define eps -INT_MAX
#define P system("pause")
using namespace std;
int a[N];
int pre[N],dp[N];
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);cc
int n,m,i,j;
int maxx;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(pre,0,sizeof(pre));
// memset(dp,0,sizeof(dp));
dp[0]=0;
for(i=1;i <= m;i++){ //分成i段
maxx=eps;
for(j=i;j<=n;j++)
{
dp[j]=max( pre[j-1],dp[j-1] )+a[j]; //pre[j-1]表示第i-1行中前j-1个元素中最大的一个
pre[j-1]=maxx; //更新pre[j-1]
if(maxx<dp[j])
maxx=dp[j]; //是maxx始终是i段字段和的最大值
}
}
printf("%d\n",maxx);
}
// P;
return 0;
}