标签:代码 tar set memset stream targe size 传送门 ref
分析
一眼看去我们自然会想到dp[i][j][k]表示区间[i,j]中选k个子段的最大值。然后我们考虑降去一维。我们设dp[i][j]表示考虑了前i个数,在选了a[i]的情况下共有j个子段的最大值,于是可以列出转移方程式dp[i][j]=Max{dp[i-1][j],Max{dp[k][j-1](k<i)}}+a[i],但是我们发现空间和时间都会爆炸,空间问题我们可以用滚动数组来进行解决,而对于时间问题我们可以记录一个dpmax[i][j]表示Max{dp[k][j](k<=i)}的值,注意这个dpmax数组同样也要滚动,于是我们就可以将转移复杂度变到O(1),在适当剪枝就可以AC啦。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
long long dp[2][6000],dpmax[2][6000],a[6000],cnt,sum;
int main(){
long long n,m,i,j,k;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
long long now=0;
for(i=1;i<=n;i++){
now^=1;
memset(dp[now],0,sizeof(dp[now]));
for(j=1;j<=min(i,m);j++){
dp[now][j]=max(dp[now^1][j],dpmax[now^1][j-1]);
dp[now][j]+=a[i];
dpmax[now][j]=max(dp[now][j],dpmax[now^1][j]);
}
}
printf("%lld\n",dpmax[now][m]);
return 0;
}
标签:代码 tar set memset stream targe size 传送门 ref
原文地址:https://www.cnblogs.com/yzxverygood/p/9692806.html