• bzoj 1010 [HNOI2008]玩具装箱


    Bzoj 1010 [hnoi2008]toy

    题目大意:给n个数,求将这些数切成数段,每段的长度为(sum+(i-j+1)-l)^2,求总的长度和最小。

    裸dp   dp[i] := min(dp[k] + (f[i]-f[j]-c)  有 i<j,f[i] = sum[i] + I;  c = l+1

    把方程转化为 y=kx+ans,ans即我们要求的数,x,y,k通过枚举的j可知,所以在斜率一定的情况下,直线 k?+ans 第一个碰到的决策点即使ans最小。

    然后通过斜率优化,可以证明决策点的最优,构建维护一个单调队列(点与点之间的斜率单调递增)(队尾维护),然后队首则维护首2点斜率大于k(k也可以推出随i增加单调的)

    {补充:单调队列维护下凸性,队首维护解决当前最优解,队尾维护则是删除上凸点}

    Dp[x] = min(dp[i]+(f[x]-f[i]-c)^2)

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

    设 dp[x]-f[x]^2=G     dp[i]+(f[i]+c)^2 = Ti   2(f[i]+c) = Hi

    原式 =  G = Ti –f[x]Hi

    直线 =  Ti = G+f[x]Hi

    斜率 = Tj-Ti / Hj-Hi

    感谢这两篇文章带领我认识斜率优化

    这个分析的很论文很像,托这个的福才顺利理解了原理的

    http://hi.baidu.com/ext_newbie/blog/item/98f66c31875426250a55a9de.html

    这个跳得有点快,直接上斜率,没有突出点的形式,让我有点费解,但是很简洁,看不懂也是因为神牛对我的bs吧= =

    http://blog.sina.com.cn/s/blog_5e6fc6d60100vp2j.html

    以及国家队2004论文

    一句话:使转移点呈现单调递增函数的模样,然后有一条斜率单调递增的直线与这个函数相切,切点为ans。

    View Code
     1 //bzoj 1010 [hnoi2008] toy
     2 const
     3         maxn=51111;
     4         inf='1.txt';
     5 var
     6         dp, f: array[0..maxn]of qword;
     7         q: array[0..maxn]of longint;
     8         n, l: longint;
     9         c: int64;
    10 procedure init;
    11 var
    12         i: longint;
    13 begin
    14   fillchar(dp, sizeof(dp), 0);
    15   fillchar(f, sizeof(f), 0);
    16   readln(n, l);
    17   for i := 1 to n do begin
    18     readln(f[i]); f[i] := f[i] + f[i-1] + 1;
    19   end;
    20   c := l + 1;
    21 end;
    22 
    23 function g(j, i: longint): qword;
    24 begin exit(dp[i]+(f[i]+c)*(f[i]+c)-dp[j]-(f[j]+c)*(f[j]+c)); end;
    25 
    26 function s(j, i: longint): qword;
    27 begin exit(2*(f[i]-f[j])); end;
    28 
    29 procedure main;
    30 var
    31         j, head, tail, i, u, x, y, z: longint;
    32 begin
    33   head := 1; tail := 1;
    34   q[tail] := 0;
    35   for i := 1 to n do begin
    36     while (head<tail)and(g(q[head], q[head+1])<=f[i]*s(q[head], q[head+1])) do inc(head);
    37     u := q[head];
    38     dp[i] := dp[u] + (f[i]-f[u]-c)*(f[i]-f[u]-c);
    39     inc(tail); q[tail] := i;
    40     while (head+2<=tail) do begin
    41       x := q[tail-2]; y := q[tail-1]; z := q[tail];
    42       if not(g(x, y)*s(y, z)<g(y, z)*s(x, y)) then begin
    43         q[tail-1] := q[tail]; dec(tail);
    44       end
    45       else break;
    46     end;
    47   end;
    48 
    49 end;
    50 
    51 procedure print;
    52 begin
    53   writeln(dp[n]);
    54 end;
    55 
    56 begin
    57   assign(input,inf); reset(input);
    58   init;
    59   main;
    60   print;
    61 end.
  • 相关阅读:
    hiho150周
    hdu1011
    hiho1055/hdu1561
    bat脚本启动exe并打开文件后退出 + 中文乱码
    hiho1080
    hiho1079
    java异常处理——基础篇
    找不到要编译的文件——path环境变量配置
    MVC——studying
    轻松搞定EasyUI
  • 原文地址:https://www.cnblogs.com/wmzisfoolish/p/2444121.html
Copyright © 2020-2023  润新知