题目:click
题意:将n个元素的数组分为k段不连续的的数组,使之和最大。
1: dp[i][j]:分为i段 以j结尾的最大值。
转移方程易得dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][i-1,i,…,j-1]+a[j]))
因为只与i和i-1有关,数组可降为一维,用一个数组维护上一层的最大值即可。
2: dp[i][j][k]:分为i段 前j个 k表示是否以j结尾的最大值。
本质思路同上,可以化为二维dp,但是注意dp[i][i][0]不可能的情况改为负无穷大。
两种思路的代码:
1
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
ll dp[5010][5010];//分为i组 以j结尾的最大值
ll a[5010];
ll MAX1[5010],MAX2[5010];
int main()
{
memset(dp,0,sizeof(dp));
int n,k,i,j;
scanf("%d %d",&n,&k);
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
dp[i][i]=a[i]+dp[i-1][i-1];
}
for(i=1;i<=k;i++)
{
for(j=i;j<=n;j++)
MAX2[j]=MAX1[j];
MAX1[i]=dp[i][i];
for(j=i+1;j<=n;j++)
{
dp[i][j]=dp[i][j-1]+a[j];
dp[i][j]=max(dp[i][j],MAX2[j-1]+a[j]);
MAX1[j]=max(MAX1[j-1],dp[i][j]);
}
}
ll ans=dp[k][k];
for(i=k+1;i<=n;i++)
ans=max(ans,dp[k][i]);
printf("%lld",ans);
return 0;
}
2
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
ll dp[5010][5010][2];//分为i组 前j个数 是否以j结尾 的最大值
ll a[5010];
ll MAX1[5010],MAX2[5010];
int main()
{
memset(dp,0,sizeof(dp));
int n,k,i,j;
scanf("%d %d",&n,&k);
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(i=1;i<=k;i++)
{
dp[i][i][1]=a[i]+dp[i-1][i-1][1];
dp[i][i][0]=-llinf;
for(j=i+1;j<=n;j++)
{
dp[i][j][1]=max(dp[i-1][j-1][1],dp[i-1][j-1][0])+a[j];
dp[i][j][1]=max(dp[i][j-1][1]+a[j],dp[i][j][1]);
dp[i][j][0]=max(dp[i][j-1][0],dp[i][j-1][1]);
}
}
ll ans=max(dp[k][k][1],dp[k][k][0]);
for(i=k+1;i<=n;i++)
{
ans=max(ans,dp[k][i][0]);
ans=max(ans,dp[k][i][1]);
}
printf("%lld",ans);
return 0;
}