题意:给定 n 个整数 和 m,求选取 m 段 连续不相交的整数 [Li,Ri] (i<=m) 使得和最大;
分析:设 dp[i][j] 表示前i个数取 m 段(第i个必取)的最大值,则初步转移方程有:
dp[i][j]=max(dp[i-1][j],dp[j~(i-1)][j-1])+a[i];
二维数组开不下,且因为第二维 j 的转移有规律,所以可以消去第二维用滚动数组,然后记 pre[i]=max(dp[1~i][j]) 维护即可;
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1E6+10;
ll dp[N],pre[N];
int a[N];
int n,m;
int main()
{
while(~scanf("%d%d",&m,&n)){
memset(dp,0,sizeof(dp));
memset(pre,0,sizeof(pre));
ll HHH;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int j=1;j<=m;j++){
HHH=-(1ll<<60);
for(int i=j;i<=n;i++){
dp[i]=max(dp[i-1],pre[i-1])+a[i];
pre[i-1]=HHH;
HHH=max(HHH,dp[i]);
}
}
printf("%lld\n",HHH);
}
}