• BZOJ-1010 玩具装箱toy (斜率优化)


    题目大意:将n个数分成若干组,并且每组的数在原数组中应是连续的,每组会产生的代价为sum(i)-sum(j)+i-j-1-m,m为已知的常数。求最小代价。

    题目分析:定义dp(i)表示将前 i 个元素分好组后产生的最小代价,状态转移方程很显然了:

    dp(i)=min(dp(j)+[sum(i)-sum(j)+i-j-1-m)]^2)。另f(i)=sum(i)+i,并且另g(i)=f(i)-1-m,则dp(i)可整理成dp(i)=min(dp(j)+sum(j)^2-2*g(i)*sum(j))+g(i)。很显然需要斜率优化。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int N=50005;
    
    int n,m;
    int q[N];
    LL a[N];
    LL dp[N];
    LL sum[N];
    
    void read(LL &x)
    {
        char ch=' ';
        while(ch<'0'||ch>'9')
            ch=getchar();
        x=0;
        while(ch>='0'&&ch<='9'){
            x=x*10+ch-'0';
            ch=getchar();
        }
    }
    
    void init()
    {
        sum[0]=0;
        for(int i=1;i<=n;++i){
            read(a[i]);
            sum[i]=a[i]+sum[i-1];
        }
        for(int i=1;i<=n;++i)
            sum[i]+=i;
    }
    
    LL getSon(int k,int j)
    {
        return dp[j]-dp[k]+(sum[j]+sum[k])*(sum[j]-sum[k]);
    }
    
    LL getMother(int k,int j)
    {
        return 2*(sum[j]-sum[k]);
    }
    
    double getK(int i,int j)
    {
        return (double)getSon(i,j)/(double)getMother(i,j);
    }
    
    LL toDp(int j,int i)
    {
        return dp[j]+(sum[i]-sum[j]-m-1)*(sum[i]-sum[j]-m-1);
    }
    
    LL solve()
    {
        int head=0,tail=-1;
        q[++tail]=0;
        dp[0]=0;
        for(int i=1;i<=n;++i){
            while(head+1<=tail&&getK(q[head],q[head+1])<=sum[i]-m-1)
                ++head;
            dp[i]=toDp(q[head],i);
            while(head+1<=tail&&getK(q[tail-1],q[tail])>getK(q[tail],i))
                --tail;
            q[++tail]=i;
        }
        return dp[n];
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            printf("%lld
    ",solve());
        }
        return 0;
    }
    

      

  • 相关阅读:
    shell编程
    redis不重启,切换RDB备份到AOF备份
    java中接口和抽象类的区别
    java中的泛型
    java中有关初始化的问题
    java中的多态
    java中的Iterator和ListIterator的区别
    Collection集合的三种初始化方法
    java正则表达式appendReplacement和appendTail方法
    java中main函数的String[] args
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5304427.html
Copyright © 2020-2023  润新知