zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    }

    orz jzy大佬

  • 相关阅读:
    Python之Sklearn使用教程
    Centos 查看路径下所有文件中是否包含指定字符
    Centos7x 开启6379端口,Centos7x开启端口
    分享几个ip定位api【转】
    @Scheduled(cron = "* * * * * *")
    QueryRunner的使用
    linux redis重置密码、重启
    nginx里的sticky的作用
    windows环境xampp搭建php电商项目/搭建禅道
    hive中解决中文乱码
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11254667.html
Copyright © 2011-2022 走看看