zoukankan      html  css  js  c++  java
  • P2389 电脑班的裁员

    题意:长度为n的序列,选出k个连续的字段,使和最大(有负数)

    暴力只选正数且不考虑k的边界问题50(数据。。。

    正解从$O(n^3)到O(n)$不等,($O(n)$不会

    DP

    1、$O(n^3)$

    以f[i][j]代表前i个数,选j段的最大ans

    当前数不选:f[i-1][j]

    当前数选:f[l][j-1]+s[i]-s[l](s为前缀和)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    #define int long long
    #define olinr return
    #define _ 0
    #define love_nmr 0
    #define DB double
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            x=-x;
            putchar('-');
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    int a[505];
    int n;
    int s[505];
    int k;
    int tot;
    int f[505][505];
    signed main()
    {
        n=read();
        k=read();
        for(int i=1;i<=n;i++)
            s[i]=s[i-1]+(a[i]=read());
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=k;j++)
            { 
                f[i][j]=f[i-1][j];
                for(int l=0;l<i;l++)
                {
                    f[i][j]=max(f[i][j],f[l][j-1]+s[i]-s[l]);
                }
            }
        }
        put(f[n][k]);
        olinr ~~(0^_^0)+love_nmr;
    }
    View Code

    2、$O(n^2)$优化(1)

    对于f[l][j-1]-s[l]的最大值可以一边DP一边处理出来

    这样就减少了一维的枚举

    注意要先枚举j,这样才能处理出

    因为l<i,所以在枚举i的时候可以处理出(1---i-1,j)的最大值,直接转移

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    #define int long long
    #define olinr return
    #define _ 0
    #define love_nmr 0
    #define DB double
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            x=-x;
            putchar('-');
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    int a[505];
    int n;
    int s[505];
    int k;
    int tot;
    int f[505][505];
    signed main()
    {
        n=read();
        k=read();
        for(int i=1;i<=n;i++)
            s[i]=s[i-1]+(a[i]=read());
        for(int j=1;j<=k;j++)
        {
            int maxn=0;
            for(int i=1;i<=n;i++)
            { 
                f[i][j]=max(f[i-1][j],maxn+s[i]);   
                maxn=max(maxn,f[i][j-1]-s[i]);
            }
        }
        put(f[n][k]);
        olinr ~~(0^_^0)+love_nmr;
    }
    View Code

    3、$O(n^2),空间O(n)$

    以f[i][j]代表前i个分成j段,第i个可以不选的ans

    以g[i][j]代表前i个分成j段,第j个必须选的ans

    g[i][j]=max(g[i-1][j],f[i-1][j-1])+a[i]

    f[i][j]=max(f[i-1][j],g[i][j])

    显然第一维可以滚动掉(类似01背包倒着枚举)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    #define int long long
    #define olinr return
    #define _ 0
    #define love_nmr 0
    #define DB double
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            x=-x;
            putchar('-');
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    int a[505];
    int n;
    int k;
    int tot;
    int g[505];
    int f[505];
    signed main()
    {
        n=read();
        k=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        for(int i=1;i<=n;i++)
            for(int j=k;j>=1;j--)
            {
                g[j]=max(g[j],f[j-1])+a[i];
                f[j]=max(f[j],g[j]);
            }
        put(f[k]);
        olinr ~~(0^_^0)+love_nmr;
    }
    View Code
  • 相关阅读:
    React Native 触摸事件处理详解
    ReactNative iOS源码解析
    windows CMD命令大全及详细解释和语法
    Node.js的全局对象和全局变量
    移动端HTML5<video>视频播放优化实践
    HTML和CSS代码片段快速编写方式(Emmet Documentation)
    animate.css官网
    Gradle在大型Java项目上的应用
    Gradle学习系列
    Gradle -- buildScript块与allprojects块及根级别的repositories区别
  • 原文地址:https://www.cnblogs.com/olinr/p/9589961.html
Copyright © 2011-2022 走看看