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.
posted @ 2012-04-12 15:52  F.D.His.D  阅读(250)  评论(0编辑  收藏  举报