CF1197D Yet Another Subarray Problem

DP

首先可以发现要增加$m$个元素才对答案产生影响

那么记$dp[i][j]$为前$i$个且连续了$j$个元素的最大值

然后就是转移

一开始我对于每一个$i$,$j$都去枚举前$m$个元素进行转移,但这是不必要的

后来$jinzy$大佬将我的$dp$转移简化了,从原来$O(m)$的转移简化到了$O(1)$

因为确定了i和j就可以确定这串元素的开头集合,那么动态规划的性质

只要找出之前的元素进行转移即可,那么对于前面的元素可以任意选取

$jzy$大佬选了前1个元素$dp$

$jzy$大佬的程序,还有他的博客

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll inf=200000000000000;
 
int n,m;
ll ans=0,dp[300005][20],sum[300005],a[300005],k;
 
int main()
{
    scanf("%d%d%lld",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++) dp[i][j]=-inf;
    }
    dp[1][1]=a[1]-k; 
    for(int i=2;i<=n;i++)
    {
        dp[i][1]=a[i]-k;
        for(int j=1;j<=min(i,m);j++)
        {
            if(j==1) dp[i][j]=max(dp[i][j],dp[i-1][m]+a[i]-k);//其实只要从前1个元素转移过来
            else dp[i][j]=max(dp[i][j],dp[i-1][j-1]+a[i]); 
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++) ans=max(ans,dp[i][j]);
    }
    cout<<ans<<endl;
    return 0;
}

我当时写的暴力dp

#include <bits/stdc++.h>
#define ll long long
#define inf 1e18
using namespace std;
const ll MAXN=3*1e5+100;
ll n,m,k,dp[MAXN][12],a[MAXN],sum[MAXN];
int main()
{
    scanf("%lld%lld%lld",&n,&m,&k);
    for (ll i=1;i<=n;i++)
      scanf("%lld",&a[i]);
    for (ll i=1;i<=n;i++)
      sum[i]=sum[i-1]+a[i];
    for (ll i=1;i<=n;i++)
    {
        for (ll j=1;j<=m;j++)
          dp[i][j]=-inf;
    }
    dp[1][1]=a[1]-k;
    for (ll i=2;i<=n;i++)
    {
        dp[i][1]=a[i]-k;
        for (ll j=1;j<=min(m,i);j++)
        {
            for (ll p=max((ll)1,i-m);p<i;p++)
            {
                if (j>p)
                  continue;
                int d;
                d=i-p;
                if (j+d>m)
                  dp[i][j+d-m]=max(dp[i][j+d-m],dp[p][j]+sum[i]-sum[p]-k);
                else
                  dp[i][j+d]=max(dp[i][j+d],dp[p][j]+sum[i]-sum[p]);
            }
        }
    }
    ll ans=0;
    for (ll i=1;i<=n;i++)
    {
        for (ll j=1;j<=min(m,i);j++)
          ans=max(ans,dp[i][j]);
    }
    printf("%lld\n",ans);
}

orz jzy大佬

猜你喜欢

转载自www.cnblogs.com/huangchenyan/p/11254667.html