• bzoj1010[HNOI2008] 玩具装箱toy


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

    Input

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

    Output

    输出最小费用

    Sample Input

    5 4
    3
    4
    2
    1
    4

    Sample Output

    1

    题解

    2014.3.20

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

    令f[i]=sum[i]+i,c=1+l

    则dp[i]=min(dp[j]+(f[i]-f[j]-c)^2)

    1.证明决策单调性

    假设在状态i处的k决策优与j决策,即

    dp[k]+(f[i]-f[k]-c)^2<=dp[j]+(f[i]-f[j]-c)^2

    则对于i后的所有状态t,要证明决策单调性

    即dp[k]+(f[t]-f[k]-c)^2<=dp[j]+(f[t]-f[j]-c)^2

    只要证

    dp[k]+(f[i]+v-f[k]-c)^2<=dp[j]+(f[i]+v-f[j]-c)^2

    只要证

    dp[k]+(f[i]-f[k]-c)^2+2*v*(f[i]-f[k]-c)+v^2<=dp[j]+(f[i]-f[j]-c)^2+2*v*(f[i]-f[j]-c)+v^2

    只要证

    2*v*(f[i]-f[k]-c)<=2*v*(f[i]-f[j]-c)

    即f[k]>=f[j](显然)

    证明完毕

    2.求斜率方程

    因为dp[k]+(f[i]-f[k]-c)^2<=dp[j]+(f[i]-f[j]-c)^2

    展开

    dp[k]+f[i]^2-2*f[i]*(f[k]+c)+(f[k]+c)^2<=dp[j]+f[i]^2-2*f[i]*(f[j]+c)+(f[j]+c)^2

    dp[k]-2*f[i]*(f[k]+c)+(f[k]+c)^2<=dp[j]-2*f[i]*(f[j]+c)+(f[j]+c)^2

    即(dp[k]+(f[k]+c)^2-dp[j]-(f[j]+c)^2)/2*(f[k]-f[j])<=f[i]

    f[i]是单调递增的,我们使用队列维护一个下凸壳,每次取出队头作为决策

    加入决策i时,令队尾为q[r],前一个为q[r-1]

    满足斜率(q[r],i)<斜率(q[r-1],q[r])时,显然队尾是无效的,将其弹出

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define ll long long
     7 #define N 50007
     8 using namespace std;
     9 
    10 int n,L,l,r;
    11 int c[N],q[N];
    12 ll s[N],f[N],C;
    13 
    14 double slop(int j,int k)
    15 {
    16     return (f[k]-f[j]+(s[k]+C)*(s[k]+C)-(s[j]+C)*(s[j]+C))/(2.0*(s[k]-s[j]));
    17 }
    18 int main()
    19 {
    20     scanf("%d%d",&n,&L);
    21     C=L+1;
    22     for(int i=1;i<=n;i++)
    23     {
    24         scanf("%d",&c[i]);
    25         s[i]=s[i-1]+c[i];
    26     }
    27     for (int i=1;i<=n;i++) s[i]+=i;
    28     l=r=1,q[r]=0;
    29     for(int i=1;i<=n;i++)
    30     {
    31         while(l<r&&slop(q[l],q[l+1])<=s[i])l++;
    32         int t=q[l];
    33         f[i]=f[t]+(s[i]-s[t]-C)*(s[i]-s[t]-C);
    34         while(l<r&&slop(q[r],i)<slop(q[r-1],q[r]))r--;
    35         q[++r]=i;
    36     }
    37     printf("%lld
    ",f[n]);
    38 }
  • 相关阅读:
    用错每日活跃用户(DAU)这个指标,无异于挖坑给自己跳
    自我修复型设计-常用的架构设计原则
    UParams
    nodejs的使用场景
    问题
    GitHub Copilot可对整行或全部代码给出AI分析建
    Your AI pair programmer
    飞冰React框架如何配置懒加载
    【630】keras 实现多输出模型
    【629】图像增强(imgaug 包)
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7598945.html
Copyright © 2020-2023  润新知