zoukankan      html  css  js  c++  java
  • 【bzoj1010】玩具装箱toy——斜率优化dp

    题目链接

    第一道自己推的斜率优化dp><

    首先要明确一点:装进同一个容器的toys一定要是连着的几个(否则的话可以直接贪心)-->之前理解错题意WA了一次......

    用sum[i]表示前缀和,f[i]表示前i个装进容器的最小费用,

    容易知道

      f[i]=max(f[i],f[j]+(sum[i]-sum[j]+i-(j+1)-l)2)(j<i)

    令k<j<i,若要使f[j]>f[k],则需要满足:

      f[j]+(sum[i]-sum[j]+i-(j+1)-l)2<f[k]+(sum[i]-sum[k]+i-(k+1)-l)2

    t[i]=sum[i]+i,则移项,可得:

      f[j]-f[k]+(t[j]-t[k])*(t[j]+t[k])<2(t[i]-l-1)(t[j]-t[k])

    即:

      (f[j]-f[k]+t[j]2-t[k]2)/(t[j]-t[k])<2*(t[i]-l-1)

    g[i]=f[i]+t[i]2,则有

      (g[j]-g[k])/(t[j]-t[k])<2*(t[i]-l-1)。

    用s(i,j)表示i到j连线的斜率,

    对于一个单调队列,每次对于队首,若s(q[h],q[h+1])<2*(ti-l-1),则此时的q[h]一定不会是现在和以后的最优解,h++;

    对于队尾,若s(q[t-2],q[t-1])>s(q[t-1],i),如果s(q[t-2],q[t-1])<2*(t[i]-l-1),则s(q[t-1],i)<2*(t[i]-l-1),由i>q[t-1]可知此时i比q[t-1]要优;如果s(q[t-2],q[t-1])>2*(t[i]-l-1),则q[t-2]要比q[t-1]优。所以无论如何q[t-1]都不会是最优解,此时t--。

    接着就是斜率优化dp的套路了:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 typedef long long LL;
     5 const int maxn=5e4+5;
     6 using namespace std;
     7 LL a[maxn],q[maxn],sum[maxn],g[maxn],t[maxn],f[maxn];
     8 inline LL read()
     9 {
    10     LL anss=0,f=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){anss=anss*10+c-48;c=getchar();}
    13     return anss*f;
    14 }
    15 inline double cal(LL a,LL b)
    16 {
    17     return 1.0*(g[a]-g[b])/(t[a]-t[b]);
    18 }
    19 int main()
    20 {
    21     int n,l;
    22     sum[0]=0;
    23     scanf("%d %d",&n,&l);
    24     for(int i=1;i<=n;i++){
    25         a[i]=read();
    26         sum[i]=sum[i-1]+a[i];
    27         t[i]=sum[i]+i;
    28     }
    29     int h=0,ta=1;q[0]=0;
    30     for(int i=1;i<=n;i++)
    31     {
    32         while(h<ta-1&&cal(q[h],q[h+1])<2*(t[i]-l-1))h++;
    33         f[i]=f[q[h]]+(t[i]-t[q[h]]-l-1)*(t[i]-t[q[h]]-l-1);
    34         g[i]=f[i]+t[i]*t[i];
    35         while(h<ta-1&&cal(q[ta-1],q[ta-2])>cal(q[ta-1],i))ta--;
    36         q[ta++]=i;
    37     }
    38     printf("%lld",f[n]);
    39     return 0;
    40 }
    bzoj1010
  • 相关阅读:
    [HDU3247]Resource Archiver
    [POJ2243]考研路茫茫——单词情结
    [POJ2778]DNA Sequence
    [bzoj3670] [Noi2014]动物园
    [bzoj3786] 星系探索
    [bzoj1493] [NOI2007]项链工厂
    postgreSQL的设置自增主键初始值
    postgreSQL绝对值
    GitHub上新建或删除仓库Repository
    Intellij Idea上传本地项目到Git
  • 原文地址:https://www.cnblogs.com/JKAI/p/7460495.html
Copyright © 2011-2022 走看看