zoukankan      html  css  js  c++  java
  • [HNOI2008]玩具装箱TOY(斜率优化)

    [HNOI2018]玩具装箱TOY

    这道题需要用到斜率优化,不会的同学点此

    题目描述

    P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为x=j-i+(sum_{K=i}^{j}{CK})制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过L。但他希望费用最小.

    输入输出格式

    输入格式:

    第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7

    输出格式:

    输出最小费用

    输入输出样例

    输入样例:
    5 4
    3
    4
    2
    1
    4

    输出样例:
    1

    这道题目是一道很好的斜率优化入门题,状态转移方程应该不难得出

    [dp[i]=min(dp[j]+(sum[i]+i-sum[j]-j-L-1)^2) (j<i) ]

    (sum[i]) 为前缀和,表示放入前i件物品所占的长度。

    [a[i]=sum[i]+i-L-1 ]

    [b[j]=sum[j]+j ]

    那么此时dp方程可转化为

    [dp[i]=dp[j]+(a[i]-b[j])^2 (j<i) ]

    进一步化简

    [dp[i]=dp[j]+a[i]^2-2*a[i]*b[j]+b[j]^2 ]

    移项,得

    [dp[j]+b[j]^2=2a[i]*b[j]+dp[i]-a[i]^2 ]

    如果你学会了斜率优化,到这一步就很明了了
    (b[j])看作(x)(dp[j]+b[j]^2)看作(y),斜率为(2a[i])的直线
    (ecause) (a[i]) 单调递增
    ( herefore) 我们需要维护一个下凸包
    (ecause) (b[j])也单调递增
    ( herefore) 用队列维护即可

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll read()
    {
        ll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*w;
    }
    ll dp[50010],sum[50010];
    ll team[50010];
    long long get(int x)
    {
        return dp[x]+(x+sum[x])*(x+sum[x]);
    }
    int main()
    {
        int n=read(),lll=read(),a;
        for(int i=1;i<=n;i++)
        {
            a=read();
            sum[i]=sum[i-1]+a;
        }
        dp[0]=0;
        int l=1,r=1;
        for(int i=1;i<=n;i++)
        {
            ll qwe=i+sum[i]-lll-1;
            while(l<r&&get(team[l+1])-get(team[l])<=2*qwe*(team[l+1]-team[l]+sum[team[l+1]]-sum[team[l]])) l++;
            dp[i]=get(team[l])-2*qwe*(team[l]+sum[team[l]])+qwe*qwe;
            while(l<r&& (get(team[r])-get(team[r-1])) * (i+sum[i]-team[r]-sum[team[r]]) >= (get(i)-get(team[r])) * (team[r]+sum[team[r]]-team[r-1]-sum[team[r-1]]) )
            r--;
            team[++r]=i;
            /*for(int j=0;j<i;j++)
            {
                if(dp[i]>dp[j]+(i-j-1+sum[i]-sum[j]-l)*(i-j-1+sum[i]-sum[j]-l))
                {
                    dp[i]=dp[j]+(i-j-1+sum[i]-sum[j]-l)*(i-j-1+sum[i]-sum[j]-l);
                }
            }*/
        }
        cout<<dp[n];
    }
    
  • 相关阅读:
    许多其他C++的class样本
    cocos2d-x 3.2 它 2048 —— 第三
    hdu 4035 可能性DP 成都网络游戏
    OpenWrt 主的发展版本号trunk MT7620N 无线驱动程序bug
    [leetcode]Permutation Sequence
    Java Swing编程接口(30)---列表框:JList
    [创新工场]2014创新工场校园招聘回文字符串维修
    FFmpeg来源简单分析:结构会员管理系统-AVClass
    [Angular 2] Component relative paths
    [TypeScript] Reflection and Decorator Metadata
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9064310.html
Copyright © 2011-2022 走看看