对于斜率优化的DP转移方程,一般以w[i]=max(w[j]+(sum[i]-sum[j])*v)的1D1D形式为主,直观看来就是前j个为若干个阶段,第j+1到第i个为一个阶段,每个阶段有自己的代价或价值。

  我们从一道题来入手,bzoj 1911 http://61.187.179.132/JudgeOnline/problem.php?id=1911 这是一道典型的斜率优化题,作为练手的入门题再适合不过。

  这道题的大概意思为将1-n个数划分为若干区间,每个区间有一个价值=a*Σ(a[i])^2+b*Σ(a[i])+c,最后使代价和最大。

  设前缀和为sum,那么很容易写出转移方程w[i]:=max(w[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+c),但是这样的时间复杂度为n^2,显然不能通过全部测试数据。那么我们考虑斜率优化。

  假设当前需要转移到第i个数,对于i的最优解为j,那么我们需要证明对于任意k>j都有j比k更优。(k<j时下文会提到)

  那么我们可以得到式子w[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+c>w[k]+a*(sum[i]-sum[k])*(sum[i]-sum[k])+c

  经整理我们可以得到(w[j]+a*sum[j]*sum[j]-b*sum[j])-(w[j]+a*sum[j]*sum[j]-b*sum[j])>2*a*sum[i]*(sum[j]-sum[k])

  因为j<k且数列的每一项>0所以sum[j]-sum[k]<0,所以我们将sum[j]-sum[k]除到式子的左面,那么可以得到

  

  ((w[j]+a*sum[j]*sum[j]-b*sum[j])-(w[j]+a*sum[j]*sum[j]-b*sum[j]))/(sum[j]-sum[k])<2*a*sum[i]

  显然对于式子的右面,只与当前的i有关,与j与k无关,那么式子的左面,我们可以将他写成类似于斜率的式子。

  设g(i)=w[i]+a*sum[i]*sum[i]-b*sum[i],那么式子可以写成((g(j)-g(k))/(sum[j]-sum[k]))<2*a*sum[i],也就是说当g(j)与g(k)满足当前关系时,j比k更优,那么我们将g(i)当成纵坐标,sum[i]当成横坐标,就可以将转移表示为坐标系中的斜率

  因为sum为递增的,我们可以维护这样的一个下凸壳,这个凸壳满足一些性质:

  首先对于队首向后考虑,每两个相邻的元素的斜率为递增的,再考虑斜率的表达式

  ((w[j]+a*sum[j]*sum[j]-b*sum[j])-(w[j]+a*sum[j]*sum[j]-b*sum[j]))/(sum[j]-sum[k]),这也就是我们刚才证明的式子,这样的式子如果对于<2*a*sum[i]成立,即表示对于当前i状态,j优于k,那么假设队的第一二元素满足该式,之后斜率递减,则之后任意两个相邻的元素都满足。这代表队首的状态优于队的第二个,同时优于之后每一个元素,即j为当前转移的i的最优解。

  那么假设当前队首与第二元素的斜率大于2*a*sum[i],那么代表队中第二元素状态优于队首,那么对于之后的任意2*a*sum[j],sum[j]为递增,a<0,所以这里为递减的,即2*a*sum[i]>2*a*sum[j],又因为k(队首,队第二)>2*a*sum[i]>2*a*sum[j],所以对于之后的所有状态,队中第二元素都优于第一元素,所以队首没有价值了,出队即可。

  进队时,因为需要满足第一性质中斜率不断减小的性质,所以保证k(队末-1,队末)< k(队末-1,当前元素)就行了。具体的证明可以去看这里的报告http://akheyun.blog.163.com/blog/static/138249276201071372635257/

/**************************************************************
Problem:
User: BLADEVIL
Language: Pascal
Result: Accepted
Time: ms
Memory: kb
****************************************************************/ //By BLADEVIL
var
w, g :array[..] of int64;
sum :array[..] of longint;
q :array[..] of longint;
a,b,c :int64;
n :longint; procedure init;
var
i :longint;
begin
read(n); read(a,b,c);
for i:= to n do
begin
read(sum[i]);
sum[i]:=sum[i]+sum[i-];
end;
end; function k(x,y:longint):extended;
begin
k:=(g[y]-g[x])/(sum[y]-sum[x]);
end; procedure main;
var
i :longint;
h, t :longint;
cur :extended;
begin
w[]:=;
h:=; t:=;
q[]:=;
for i:= to n do
begin
cur:=*a*sum[i];
while (t-h>)and (k(q[h],q[h+])>cur) do inc(h);
w[i]:=w[q[h]]+a*int64(sum[i]-sum[q[h]])*int64(sum[i]-sum[q[h]])+b*int64(sum[i]-sum[q[h]])+c;
g[i]:=w[i]+a*int64(sum[i])*int64(sum[i])-b*int64(sum[i]);
while (t-h+>=)and(k(q[t],i)>k(q[t-],q[t])) do dec(t);
inc(t);
q[t]:=i;
end;
writeln(w[n]);
end; begin
init;
main;
end.

斜率优化DP讲解的更多相关文章

  1. 斜率优化dp 的简单入门

    不想写什么详细的讲解了...而且也觉得自己很难写过某大佬(大米饼),于是建议把他的 blog 先看一遍,然后自己加了几道题目以及解析...顺便建议看看算法竞赛(蓝皮书)的 0x5A 斜率优化(P294 ...

  2. 斜率优化DP学习笔记

    先摆上学习的文章: orzzz:斜率优化dp学习 Accept:斜率优化DP 感谢dalao们的讲解,还是十分清晰的 斜率优化$DP$的本质是,通过转移的一些性质,避免枚举地得到最优转移 经典题:HD ...

  3. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  4. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  5. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

  6. 【BZOJ-1096】仓库建设 斜率优化DP

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Stat ...

  7. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

  8. BZOJ 3156: 防御准备 斜率优化DP

    3156: 防御准备 Description   Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战 ...

  9. HDU2829 Lawrence(斜率优化dp)

    学了模板题之后上网搜下斜率优化dp的题目,然后就看到这道题,知道是斜率dp之后有思路就可以自己做不出来,要是不事先知道的话那就说不定了. 题意:给你n个数,一开始n个数相邻的数之间是被东西连着的,对于 ...

随机推荐

  1. url解读

    我刚刚学习的时候,我抓到包不知道哪个是协议.哪个是是服务器地址.哪个是端口号...不知道有没有老铁遇到跟我一样的. 接口:http://172.168.12.0:8888/old/login.do 解 ...

  2. Page Object 设计模式介绍

    Page Object 是 Selenium 自动化测试项目开发实践的最佳设计模式之一,Page Object 的主要体现于对界面交互细节的封装,这样可以使测试案例更关注与业务而非界面细节,提高测试案 ...

  3. CodeBlocks 3 使用设置

    使用MingW作为CB的默认编译器和wxWidgets进行编程,当然需要好好配置一番,因为mingw在windows下用起来着实没有win32原生态程序运行快,也没有他小,好处是借助wxwidgets ...

  4. 21天学习caffe(二)

    本文大致记录使用caffe的一次完整流程 Process 1 下载mnist数据集(数据量很小),解压放在data/mnist文件夹中:2 运行create_mnist.sh,生成lmdb格式的数据( ...

  5. word2vec是如何工作的?

    如何有效的将文本向量化是自然语言处理(Natural Language Processing: NLP)领域非常重要的一个研究方向.传统的文本向量化可以用独热编码(one-hot encoding). ...

  6. Java开发JDBC连接数据库

    Java开发JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含6个步骤: JDBC五部曲1.加载驱动2.获得链接3.获取statement对象 4.执行SQL语句5.产生resultset对 ...

  7. Python时间获取及转换知识汇总

    时间处理是我们日常开发中最最常见的需求,例如:获取当前datetime.获取当天date.获取明天/前N天.获取当天开始和结束时间(00:00:00 23:59:59).获取两个datetime的时间 ...

  8. python中locals和globals函数

    参考:http://www.cnblogs.com/wanxsb/archive/2013/05/07/3064783.html Python有两个内置的函数,locals() 和globals(), ...

  9. postman工具【接口自动化测试关于断言】

    在使用postman工具进行接口自动化时我们经常需要断言来进行判断,结果到底是成功还是失败. 但在collection runner/Newman里如果不加断言,跑完后都无法知道是成功还是失败 断言是 ...

  10. lintcode-76-最长上升子序列

    76-最长上升子序列 给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度. 说明 最长上升子序列的定义: 最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列 ...