标签:
链接:点击打开链接
题意:n个数分成m段不相交子段和最大
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; int a[1000005],sum[1000005]; int dp[2][1000005][2]; int main(){ //因为是分成m段,因此和容易想到 int n,m,i,j,tmp; //dp[i][j]为前i个数分成j段的最大和 while(scanf("%d%d",&m,&n)!=EOF){ //但是再每次合并时,需要判断当前数是否选 memset(dp,-INF,sizeof(dp)); //因此需要再加一维记录前一个数的状态 for(i=1;i<=n;i++){ scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } tmp=-INF; dp[0][0][0]=0; for(i=1;i<=n;i++){ if(sum[i-1]+a[i]>a[i]){ dp[i%2][1][1]=sum[i-1]+a[i]; sum[i]=sum[i-1]+a[i]; } else{ sum[i]=a[i]; dp[i%2][1][1]=a[i]; } dp[i%2][1][0]=tmp; //长度是1时就是最大子段和 tmp=max(tmp,sum[i]); for(j=2;j<=m;j++){ if(i<j) break; if(i-1>=j){ //考虑i-1个数能不能分成j份 dp[i%2][j][1]=max(max(dp[(i-1)%2][j-1][0],dp[(i-1)%2][j-1][1]),dp[(i-1)%2][j][1])+a[i]; dp[i%2][j][0]=max(dp[(i-1)%2][j][0],dp[(i-1)%2][j][1]); } else{ dp[i%2][j][0]=-INF; dp[i%2][j][1]=max(dp[(i-1)%2][j-1][0],dp[(i-1)%2][j-1][1])+a[i]; } } } printf("%d\n",max(dp[n%2][m][1],dp[n%2][m][0])); } return 0; }
标签:
原文地址:http://blog.csdn.net/stay_accept/article/details/51344504