ICPC North Central NA Contest 2018 B. Maximum Subarrays

题目: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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/106635704