zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    mac下 brew 切换阿里镜像
    梨视频(PearVideo)下载解析的方法和技巧,梨视频下载到本地
    如何快速的下载Tumblr(汤不热)视频?操作步骤很简单,快来看看!
    什么是json? 什么是xml?JSON与XML的区别比较
    如何下载Twitter视频?最简单的保存推特视频的方法
    【收藏】轻松导出全民K歌里任何人录制的短视频(MV)、歌曲的方法
    【小白技术笔记】保存皮皮虾APP无水印视频到手机相册,只需要三步 [技术干货]
    技术干货!腾讯微视短视频去水印下载到本地的方法
    P1562 还是N皇后
    循环赛日程表
  • 原文地址:https://www.cnblogs.com/wmzisfoolish/p/2444121.html
Copyright © 2011-2022 走看看