zoukankan      html  css  js  c++  java
  • Codeforces 392E Deleting Substrin(区间dp)

    题目大意:

    • 给定vi,wi,每次可以在wi中选择一个子段[l,r]满足:
    • |wi-wi+1|=1 (l<=i<r)
    • 2wi-wi-1-wi+1>=0 (l<i<r)
    • 选择后获得vr-l+1的收益并把这个子段删除,可以不删完,求最大收益。
    • n<=400

    Examples
    input
    3
    0 0 3
    1 2 1
    output
    3
    input
    6
    1 4 5 6 7 1000
    2 1 1 2 2 3
    output
    12

    题解:
    我们删除的区间是一个单峰上凸的区间。
    用f[i][j]表示将i到j全部删完得到的最大代价,g[i][j]表示将i到j的区间删成w[i],w[i]+1,……,w[j]的最大收益,h[i][j]
    表示将i到j的区间删成w[i],w[i]-1,……,w[j]的最大收益。
    f[i][j]可以由f[i][k]+f[k+1][j]||g[i][k]+h[k][j]+v[2*w[k]-w[i]-w[j]+1]转移过来。
    h[i][j]和g[i][j]怎么维护呢? 当w[k]==w[i+1]时g[i][j]<-f[i+1][k-1]+g[k][j],h[i][j]同理。
    代码:
    #include<cstdio>
    #include<algorithm>
    #define inf 1<<28
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
        return;
    }
    int n,v[410],w[410],f[410][410],h[410][410],g[410][410],ans[410];
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++)read(v[i]);
        for(int i=1;i<=n;i++)read(w[i]);
        for(int l=1;l<=n;l++)
        {
            for(int i=1;i+l-1<=n;i++)
            {
                int j=i+l-1;
                if(i==j){g[i][j]=h[i][j]=0;f[i][j]=v[1];continue;}
                g[i][j]=h[i][j]=-inf;
                for(int k=i+1;k<=j;k++)
                if(w[k]==w[i]+1)g[i][j]=max(g[i][j],f[i+1][k-1]+g[k][j]);
                else if(w[k]==w[i]-1)h[i][j]=max(h[i][j],f[i+1][k-1]+h[k][j]);
                f[i][j]=-inf;
                for(int k=i;k<j;k++)
                f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
                for(int k=i;k<=j;k++)
                if(g[i][k]>-1<<20&&h[k][j]>-1<<20)f[i][j]=max(f[i][j],g[i][k]+h[k][j]+v[2*w[k]-w[i]-w[j]+1]);
            }
        }
        for(int i=1;i<=n;i++)
        {
            ans[i]=ans[i-1];
            for(int j=1;j<=i;j++)
            ans[i]=max(ans[i],ans[j-1]+f[j][i]);
        }
        printf("%d
    ",ans[n]);
        return 0;
    }
    
    
    


  • 相关阅读:
    文件上传
    gitee 提交项目
    SSM分页查询功能
    SSM 管理员删除功能
    SSM整合 管理员登录功能(密码加密功能)
    SSM整合项目 MD5加密工具类
    SSM Ajax发送复杂对象
    SSM环境中 Ajax 发送简单数组的三种方法
    ssm 增删改查
    ssm 登录功能
  • 原文地址:https://www.cnblogs.com/jiangtao0508/p/7742100.html
Copyright © 2011-2022 走看看