以下是我转载的大牛NOIAu的博客

目录

引入:

~PART ONE 交叉小于包含

~PART TWO 证明过程三步走

壹:证明cost为凸(满足四边形不等式)

贰:证明dp为凸(满足四边形不等式)

叁:证明决策单调(以找min值为例)

~PART THREE

合并石子问题

第一步(壹)证明cost为凸

第二步(贰)证明dp为凸

第三步(叁)证明决策单调

关于O(n^2)复杂度的证明

最后说一句


引入:

在dp问题中,我们经常遇见这样的一类问题 
他们的dp转移方程是这样的

dp[i][j]=min{dp[i][k]+dp[k+1][j]+cost[i][j]}

显然for一边i,for一边j,在算dp[i][j]的时候还得for一遍k,这是O(n^3)的复杂度,这样的复杂度在很多时候是不能接受的,如果dp转移方程已经设计好了,也无法再在dp方程上优化,我们怎么来提高计算效率呢?(关于O(n^2)复杂度的证明我放在最后)


~PART ONE 交叉小于包含

对于( a < b <= c< d )

如果有f[a][c]+f[b][d]<=f[b][c]+f[a][d]

(可以理解为一句话,交叉小于包含,即交叉的两个区间,a到c和b到d的值满足小于等于包含的两个区间[bc包含于ad]) 
则说这个东西满足四边形不等式,当然这个东西可能是dp数组,也可以是其他数组,比如引入里提到的cost数组,表示的是i到j的花费(比如合并石子问题)

给出两个定理:

1、如果上述的w函数同时满足区间包含单调性和四边形不等式性质,那么函数dp也满足四边形不等式性质 
我们再定义s(i,j)表示 dp(i,j) 取得最优值时对应的下标(即 i≤k≤j 时,k 处的 dp 值最大,则 s(i,j)=k此时有如下定理 
2、假如dp(i,j)满足四边形不等式,那么s(i,j)单调,即 s(i,j)≤s(i,j+1)≤s(i+1,j+1) 
如果不知道为什么,没有关系,反正后面都要证明


~PART TWO 证明过程三步走

(这一部分如果没有完全懂没有关系,PART-THREE里会结合题目来推导一遍,所以有一小部分推导在这里先不写出来,这一部分尽量先说原理和方法)


壹:证明cost为凸(满足四边形不等式)

显然,当且仅当对于所有的i,j,均满足如下式子 
(令i< i+1<= j< j+1) 
cost[i][j]+cost[i+1][j+1]<=cost[i][j+1]+cost[i+1][j] 
(利用PART ONE的交叉小于包含写出来的式子) 
转移一下式子 
即要证明对于所有的i,j,要使 
cost[i][j]-cost[i+1][j]<=cost[i][j+1]-cost[i+1][j+1] 
试想一个函数f(j)=cost[i][j]-cost[i+1][j],那么要证明这个四边形不等式成立,也就是要证明这个函数f(j)单调递增嘛


贰:证明dp为凸(满足四边形不等式)

显然我们需要证明对于任意的i,j 
i< i+1<= j< j+1 
均满足 
dp[i][j]+dp[i+1][j+1]<=dp[i+1][j]+dp[i][j+1] 
这一步其实是建立在壹的上面的,可以用壹的结论来推导贰的结论 
假设式子右边的dp[i+1][j]取得最优值的时候的k为x(之前不是要for一遍k来寻找最优时候的解嘛),右边式子里的dp[i][j+1]取得最优值的时候的k为y,这个时候把k=x带入左式的dp[i][j]中,把k=y带入左式的dp[i+1][j+1]中,然后寻找dp数组和cost数组的联系,把左边的式子配凑出右边的式子然后完成证明 
(可能看不懂这句话是什么意思,不是很擅长表达,具体的证明方式大家可以结合PART-THREE里详细论证过程来学习,如果没懂就很不舒服的,现在就可以结合PART THREE看啦)


叁:证明决策单调(以找min值为例)

如果我们用s[i][j]表示dp[i][j]取得最优解的时候k的位置的话 
那么我们要证明如下结论的成立性: 
s[i][j-1]<=s[i][j]<=s[i+1][j] 
对于s[i][j-1]<=s[i][j]来说,我们先令dp[i][j-1]取得最优解的时候的k值为y,然后令除了最优值以外的其他值可以为x,这里我们由于要讨论单调性,所以让x小于y,即x<=y<=j-1< j 
然后利用我们在壹和贰里已经证明了的结论,来列一个关于dp数组的四边形不等式,然后在两边同时加上cost数组以求拼凑出如下的结论 
dp[i][j-1] (k=x)+dp[i][j] (k=y)<=dp[i][j-1] (k=y)+dp[i][j] (k=x) 
( 这个看起来也有点奇怪,不过PART-THREE会讲具体是怎样操作的 ) 
然后进行移项 
dp[i][j-1] (k=x)-dp[i][j-1] (k=y)<=dp[i][j] (k=x)-dp[i][j] (k=y) 
可以这样理解 
我们之前是令dp[i][j-1]取得最优值的时候k=y,所以对于所有的x小于y,一定有dp[i][j-1](k=x)>=dp[i][j-1] (k=y)(因为我们这里最优值是指最小值),所以很自然的,dp[i][j] (k=x)-dp[i][j] (k=y)也必然会大于等于零,也就是说,有如下结论 
dp[i][j] (k=x)>=dp[i][j] (k=y) 
什么意思呢,让dp[i][j-1]可以取得最小值的y,对于dp[i][j]的决策来说,可以使得所有小于y的x的值都没有y优,所以dp[i][j]的最优决策一定不会小于y,所以如果我们用s[i][j]表示dp[i][j]取得最优值的时候的k值,那么一定有 
s[i][j-1]<=s[i][j] 
而s[i][j]<=s[i+1][j]的证明是类似的,读者可以自己再推一遍


~PART THREE

终于到了激动人心的详细证明过程和如何使用四边形不等式进行优化,亦可赛艇! 
看例题来讲解总是好的,这里我们就举一个大家都做过的广为熟知的题


合并石子问题

现在有n堆石子,要将石子按一定顺序地合成一堆,规定如下,每次只能移动相邻的两堆石子,合并费用为新和成一堆石子的数量,求把n堆石子全部合并到一起所花的最少或者最大花费

很容易想到这样一个dp转移 
dp[i][j]=min{dp[i][k]+dp[k+1][j]}+cost[i][j] 
震惊!这不就是之前所讲的模型嘛?原来之前O(n^3)方的合并石子问题还可以优化(我太弱了) 
首先明确一点,cost[i][j]表示把第i堆到第j堆的石子和到一起的最后一步的代价,显然,之前无论怎么合并,最后一步的代价都是一样的,所以我们可以先预处理出这个cost数组,他等于cnt[j]-cnt[i-1],其中cnt数组是前缀和 
for一遍i,for一遍j,每算一次dp[i][j]还要for一遍k,自然是O(n^3)方,现在我们来按照规则判断是否可以用四边形优化


第一步(壹)证明cost为凸

对于所有的i,j,令其满足i< i+1<=j< j+1 
我们需要证明 
cost[i][j]+cost[i+1][j+1]<=cost[i+1][j]+cost[i][j+1] 
移项 
cost[i][j]-cost[i+1][j]<=cost[i][j+1]-cost[i+1][j+1] 
令f(j)=cost[i][j]-cost[i+1][j] 
f(j)=cnt[j]-cnt[i-1]-(cnt[j]-cnt[i]) 
f(j)=cnt[i]-cnt[i-1] 
都跟j无关了,自然一定满足四边形不等式(这个时候是直接等于了,但没有违反四边形不等式)


第二步(贰)证明dp为凸

要推导dp[i][j]的凸性,自然要满足对任意的i,j,令i< i+1<=j< j+1 
有如下结论 
dp[i][j]+dp[i+1][j+1]<=dp[i+1][j]+dp[i][j+1] 
令dp[i+1][j]取得最优值的时候k=x 
令dp[i][j+1]取得最优值的时候k=y 
令x < =y(之后还要令x > y,这里不再赘述,读者如有兴趣可以自行推导,方式相似) 
将k=x代入dp[i][j],k=y代入dp[i+1][j+1] 
左式=dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i+1][y]+dp[y+1][j+1]+cost[i+1][j+1]① 
而对于i< i+1<=j< j+1 
由于已经在壹中证明了cost的凸性,所以 
cost[i][j]+cost[i+1][j+1]<=cost[i+1][j]+cost[i][j+1]② 
我们会发现这个不等式的左边在①式中出现过,所以把②式中的左式和右式替换一下可以得到如下结论 
dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i+1][y]+dp[y+1][j+1]+cost[i+1][j+1] 
<=

dp[i][x]+dp[x+1][j+1]+cost[i][j+1]+dp[i+1][y]+dp[y+1][j]+cost[i+1][j]

即dp[i][j]+dp[i+1][j+1]<=dp[i][j+1]+dp[i+1][j] 
证毕


第三步(叁)证明决策单调

现在我们已经证明了cost数组和dp数组的凸性,要证明决策单调以证明优化的正确性 
即要证明s[i][j-1]<=s[i][j]<=s[i+1][j] 
对于s[i][j-1]<=s[i][j] 
令dp[i][j-1]取得最小值时的k=y,对于所有x≠y,令x<=y 
可以有如下推导 
∵x+1<=y+1<=j-1< j 
四边形不等式有: 
dp[x+1][j-1]+dp[y+1][j]<=dp[y+1][j-1]+dp[x+1][j]

在式子两边同时加上dp[i][x]+cost[i][j-1]+dp[i][y]+cost[i][j] 可以得到

dp[i][x]+dp[x+1][j-1]+cost[i][j-1]+dp[i][y]+dp[y+1][j]+cost[i][j] 
<= 
dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i][y]+dp[y+1][j-1]+cost[i][j-1]

dp[i][j-1]+dp[i][j]<=dp[i][j]+dp[i][j-1] 
(k=x)…………(k=y)……(k=x)……(k=y) 
移项

dp[i][j-1]-dp[i][j-1]<=dp[i][j]-dp[i][j] 
(k=x)…………(k=y)……(k=x)……(k=y)

由于我们是令k=y时dp[i][j-1]取得最小值,那么dp[i][j-1] (k=x)一定大于等于dp[i][j-1] (k=y),所以左式大于零,所以右式也大于零,所以对于dp[i][j-1]可以取到最优值的y,所有小于它的值,对于dp[i][j]来说,都没有y优,所以最优决策一定不是小于y的,如果令s[i][j]表示dp[i][j]取得最优值的时候的k值,那么一定有 
s[i][j-1]<=s[i][j] 
证毕 
对于不等式后半部分的证明类似,读者有兴趣可以自己再证明一次


代码如下

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 10000+10
using namespace std;int dp[MAXN][MAXN],s[MAXN][MAXN],cnt[MAXN];
int n;void init(){scanf("%d",&n);for(register int i=1;i<=n;i++) scanf("%d",&cnt[i]),cnt[i]=cnt[i-1]+cnt[i];for(register int i=1;i<=n;i++){dp[i][i]=0;s[i][i]=i; }for(register int i=n;i>=1;i--){for(register int j=i+1;j<=n;j++){int temp=0x7fffffff;int te;for(int k=s[i][j-1];k<=s[i+1][j];k++){if(temp>dp[i][k]+dp[k+1][j]+cnt[j]-cnt[i-1]){temp=dp[i][k]+dp[k+1][j]+cnt[j]-cnt[i-1];te=k;}}dp[i][j]=temp;s[i][j]=te;}}
}void print(){cout<<dp[1][n]<<endl;
}int main(){init();print();
}

尤其要注意for的顺序,因为我们在推dp[i][j]的时候要用s[i][j-1]和s[i+1][j]所以i一定是倒序的,这样才能在求dp[i][j]的时候调用dp[i+1][j]的最优决策s[i+1][j],而j一定是顺序的,这样才能在求dp[i][j]的时候调用dp[i][j-1]的最优决策s[i][j-1]


关于O(n^2)复杂度的证明

其实证明很简单,对于一个i,j来说,我们要for s[i][j-1]到s[i+1][j]个数,那么所有的i和j加起来一共会for多少次呢? 
我们可以这样思考 
(s[2][2]-[1][1])+(s[3][3]-s[2][2])+(s[4][4]-s[3][3])+…+(s[n][n]-s[n-1][n-1])=s[n][n]-s[1][1]很显然是小于n的嘛,所以本来是(n *n *n)的复杂度,就这样降成了O(n *n)啦


最后说一句

对于dp转移合法的证明,其实很多时候我们不用像我写的这样去判断,直接打表就行了,比如先跑一个O(n^3)的代码,跑的时候判断是否满足四边形不等式,决策是否单增等等,如果不满足就输出false之类的,或者打一个决策表出来观察,这样其实会省下一部分时间,之前的所有证明,只是帮助你理解该算法(该优化)的正确性
--------------------- 
作者:NOIAu 
来源:CSDN 
原文:https://blog.csdn.net/noiau/article/details/72514812 
版权声明:本文为博主原创文章,转载请附上博文链接!

于是我附上了博文链接:点击进入

平行四边形不等式优化详解相关推荐

  1. MySQL之SQL优化详解(二)

    目录 MySQL之SQL优化详解(二) 1. SQL的执行顺序 1.1 手写顺序 1.2 机读顺序 2. 七种join 3. 索引 3.1 索引初探 3.2 索引分类 3.3 建与不建 4. 性能分析 ...

  2. lucene.NET详细使用与优化详解

    lucene.NET详细使用与优化详解 http://www.cnblogs.com/qq4004229/archive/2010/05/21/1741025.html http://www.shan ...

  3. python实现单例模式的几种方式_基于Python中单例模式的几种实现方式及优化详解...

    单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...

  4. 高效并发:Synchornized的锁优化详解

    高效并发:Synchornized的锁优化详解 1. HotSpot虚拟机的对象头的内存布局 2. 偏向锁 举一反三:当锁进入偏向状态时,存储hash码的位置被覆盖了,那对象的hash码存储到哪儿的? ...

  5. MySQL-5.5.32 配置文件优化详解

    目录 MySQL-5.5.32 配置文件优化详解 一.配置文件说明 2.my-medium.cnf 3.my-large.cnf 4.my-huge.cnf 5.my-innodb-heavy-4G. ...

  6. 网易考拉海购Dubbok框架优化详解

    网易考拉海购Dubbok框架优化详解 摘要:微服务化是当前电商产品演化的必然趋势,网易考拉海购通过微服务化打破了业务爆发增长的架构瓶颈.本文结合网易考拉海购引用的开源Dubbo框架,分享支持考拉微服务 ...

  7. 快速排序深度优化详解

    正如它的名字所体现,快速排序是在实践中最快的已知排序算法,平均运行时间为O(NlogN),最坏的运行时间为O(N^2).算法的基本思想很简单,然而想要写出一个高效的快速排序算法并不是那么简单.基准的选 ...

  8. mysql索引linke和等于_MySQL之SQL优化详解(三)

    摘要: 致索引失效而转向全表扫描存储引擎不能使用索引中范围条件右边的列mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描isnull,isnotnull也无法使用索引l ...

  9. stardict安装与优化详解

    stardict安装与优化详解 2011年10月08日 转自ubuntu中文论坛 星际译王是跨平台的国际词典软件!它功能强大,实用性强," 通配符匹配","鼠标查词&qu ...

  10. WINDOWS XP服务和进程优化详解

    WINDOWS XP服务和进程优化详解 1.Alerter Alerter(警示器)服务的进程名是Services.exe(即启动这个服务后在后台运行的进程的名称,可以通过任务管理器看到).Alert ...

最新文章

  1. 当我们在谈大前端的时候,我们谈的是什么
  2. linux交叉编译无法识别gcc编译器
  3. 【20120517】【早晨】
  4. 酷桌面:随身携带你的企业
  5. leetcode124. 二叉树中的最大路径和
  6. AI工程师的崩溃,是从你的薪资比我高开始
  7. Android 自定义View -- 简约的折线图
  8. itchat key
  9. Div被Select挡住的解决办法
  10. sharelatex在centos 6.7 64位上的部署(2)
  11. 凸函数,凸优化问题,凸二次规划问题
  12. visio 2007 简体中文版下载
  13. 所需即所获:像IDE一样使用 vim
  14. MariaDB安装教程
  15. 二层交换机与路由器的区别
  16. 为什么游戏模型不如原画好看?
  17. 云耀服务器 NumPy安装 完整过程
  18. 显著性检测的四种经典方法
  19. 哪家互联网大厂,对离职员工最“狠”?
  20. 孤尽T31项目第6天-Java项目工程结构规约

热门文章

  1. 用单分子测序(single-molecule sequencing)和局部敏感哈希(locality-sensitive hashing)来组装大型基因组...
  2. 解决vue报错:Avoided redundant navigation to current location
  3. Visio 常用的快捷键
  4. Hive分组统计前top N条记录
  5. Shell 练习题 21—30,内附答案
  6. 【教程】在线生成LaTeX中的表格
  7. 35枚不同风格的设计师个人网站欣赏
  8. 计算机多媒体专业就业现状,计算机多媒体技术就业前景怎么样
  9. 〖Python自动化办公篇㉑〗- python实现邮件自动化 - 定时发送邮件
  10. selenium自动化入门之实现163邮箱发送邮件