zoukankan      html  css  js  c++  java
  • 区间dp之四边形不等式优化详解及证明

    看了那么久的四边形不等式优化的原理,今天终于要写一篇关于它的证明了。

    在平时的做题中,我们会遇到这样的区间dp问题

     它的状态转移方程形式一般为dp[i][j]=min(dp[i][k]+dp[k+1][j]+cost[i][j]);(或者是max(........),本博客以min为例来证明)

    熟悉一般区间dp的同学应该清楚我们如果想得到最终的答案,一般要用三层for循环来计算(第一层为长度,第二层枚举起始点,第三层在起始点i和终点j之间寻找最优的分割点)。显而易见它的时间复杂度为o(n^3),但是当cost满足四边形不等式的要求时我们就可以将他优化为o(n^2)。

    为什么可以这样呢,请慢慢往下看

    首先什么是满足四边形不等式呢

    满足四边形不等式用通俗话来讲就是对于一个区间值关系,如果它满足交叉小于包含的话,那么就说它是满足四边形不等式的。

    例如当i < i' <=  j < j'时,对于cost的值来说,如果它满足   cost[i][j]+cost[i'][j']<=cost[i][j']+cost[i'][j的关系时,那么我们就说它满足四边形不等式。

    我们如果想证明一个区间值关系是否满足四边形不等式,光依靠上面的式子来判断还是有点困难的,我们不妨把上面的式子变动一下

    我们以 i+1 来替换 i‘ ,以 j+1 来替换 j’ (即  i < i+1<= j < j+1  ),得到下面的式子

    即当我们证明了 cost[i][j]+cost[i+1][j+1]<=cost[i][j+1]+cost[i+1][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 )<=F( j+1 ))

    当我们的花费数组cost[i][j]满足四边形不等式时,我们怎么将dp的时间复杂度优化为o(n^2)呢?

    不幸的是,我们还要证明dp[i][j]满足四边形不等式才行,但是dp数组是我们要求的,它不是已知的,我们怎么知道它满不满足呢。

    还记得我们刚刚证明了cost满足四边形不等式了吗,我们可以利用cost来推出dp满足四边形不等式

    即证当  i< i+1<=j< j+1 时

    dp[i][j]+dp[i+1][j+1]<=dp[i+1][j]+dp[i][j+1]

    这个证明有点抽象,我先以一道题目为例使它更加容易理解

     样例

    7

    13 7 8 16 21 4 18

    输出

    239

    我们利用数学归纳法来证明dp数组满足四边形不等式(学过高等数学的同学应该不陌生)(如果你不知道什么是数学归纳法的话请点这里

    我们要证明dp[i][j] + dp[i+1][j+1] <= dp[i][j+1]+dp[i+1][j]成立(i < i+1 <= j < j+1)

    1.当 i=1,j=2时(此时i+1=j)

    因为

    dp[1][1]=dp[2][2]=dp[3][3]=0,

    dp[1][2]=w[1][2],dp[2][3]=w[2][3],

    dp[1][3]>=w[1][3]

    而由四边形不等式可知

    w[1][2]+w[2][3]<=w[1][3]+w[2][2]

    显然dp[1][2]+dp[2][3]<=dp[1][3]+dp[2][2]成立

    2.我们令dp[i][j+1]取得最优值的时候k=x

    dp[i+1][j]取得最优值的时候k=y

    当x < =y时(之后还要令x > y的情况类似)

    我们假设dp[x+1][j] + dp[y+1][j+1] <= dp[x+1][j+1] + dp[y+1][j]   成立   (此时x+1 <= y+1 <= j < j+1)

    这一步是数学归纳法中重要的一部分,先假设小范围的成立,然后推出大范围的成立

    对于(i < i+1<=j<j+1)

    显然

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

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

    dp[i][j] + 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]

    又因为cost满足四边形不等式

     cost[i][j] +  cost[i+1][j+1] <=  cost[i][j+1] +  cost[i+1][j]

    所以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] + cost[i][j+1] + dp[i+1][y] + dp[y+1][j+1] + cost[i+1][j]

    又因为dp[x+1][j] + dp[y+1][j+1] <= dp[x+1][j+1] + dp[y+1][j]   成立  

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

    <= 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+1]+dp[i+1][j]

    即dp[i][j] + dp[i+1][j+1] <= dp[i][j+1]+dp[i+1][j] 成立

     (x+1 <= y+1 <= j < j+1)是包含在(i < i+1 <= j < j+1)里的

    综上,由数学归纳法得证dp也满足四边形不等式

    不理解的同学可以这样想想,显然dp[1][1],dp[2][2].....dp[n-1][n-1],dp[n][n]的值在本题中显然为0,它是满足四边形不等式的(此时dp长度为1

    而dp[1][2],dp[2][3].....dp[n-2][n-1],dp[n-1][n]的值显然为cost[1][2],cost[2][3].....cost[n-2][n-1],cost[n-1][n], 它是满足四边形不等式的(由dp[1][2]+dp[2][3]<=dp[1][3]+dp[2][2]成立可以类比推出来)

    (此时dp的长度为n-(n-1)+1=2,即长度为2,枚举每个起点,知道长度,得到他们的dp值)

    对于dp长度为3的值,它一定是长度小于它的dp值推出来的,所以,当长度小于它的dp值满足四边形不等式时,我们可以推出当前长度为3的dp值也满足四边形不等式

    一直只要依次推下去,就可以得到dp是满足四边形不等式的

    现在我们推出了dp是满足四边形不等式的

    我们现在就可以尝试去降低算法的时间复杂度了

    那它是怎么降低的呢?

    我们只要证明最后一样关系式就可以了

    s[i][j-1]<=s[i][j]<=s[i+1][j](s[i][j]表示dp[i][j]的最优分割点(dp[i][j]=min(t|dp[i][t]+dp[t+1][j]+cost[i][j])))

    我们令d=s[i][j-1] , k <= d

    cut=x 表示以x为分割点的dp值(即dp[i][j]=dp[i][x]+dp[x+1][j]+cost[i][j])

    构造一个式子

    (dp[i][j] - dp[i][j]) - (dp[i][j-1] - dp[i][j-1])

    cut=k       cut=d       cut=k        cut=d

     =(dp[i][j] + dp[i][j-1]) - (dp[i][j-1] + dp[i][j])

         cut=k      cut=d           cut=k        cut=d

     =(dp[i][k]+dp[k+1][j]+cost[i][j]+dp[i][d]+dp[d+1][j-1]+cost[i][j-1])-(dp[i][k]+dp[k+1][j-1]+cost[i][j-1]+dp[i][d]+dp[d+1][j]+cost[i][j] )

    =(dp[k+1][j]+dp[d+1][j-1])-(dp[k+1][j-1]+dp[d+1][j])

    因为  k+1<=d+1 <=j-1< j,由四边形不等式可知

    =dp[k+1][j]+dp[d+1][j-1] >= dp[k+1][j-1]+dp[d+1][j]

    所以

    (dp[i][j] - dp[i][j]) - (dp[i][j-1] - dp[i][j-1]) >= 0

    cut=k       cut=d       cut=k        cut=d

    移一下项

    (dp[i][j] - dp[i][j]) >= (dp[i][j-1] - dp[i][j-1])

    cut=k       cut=d         cut=k        cut=d

    又因为d是dp[i][j-1]的最优分割点

    所以

    (dp[i][j-1] - dp[i][j-1]) >=0   (因为cut=d时dp[i][j-1]取最小值,cut取其他位置时得到的值必然大于在d点切割取的值)

      cut=k        cut=d

    所以

    (dp[i][j] - dp[i][j]) >=0

    cut=k       cut=d  

    又因为k是任意小于d的数(k<=d)

    dp[i][j] >= dp[i][j]

    cut=k       cut=d  

    所以要想dp[i][j]最小,那么它的最优分割点s[i][j]必然大于等于d (d=s[i][j-1])

    即 s[i][j] >= s[i][j-1]

    证毕,同理可得

    s[i][j] <= s[i+1][j]

    有了s[i][j-1]<=s[i][j]<=s[i+1][j]这个结论

    我们就可以把第三层for循环找最优分割点的区间从(i,j) 缩小到(s[i][j-1],s[i+1][j])

    这样就把第三层for循环的时间复杂度从o(n)降到o(1)

    从而把整个时间复杂度从o(n^3)降到o(n^2)。

    本人因为知识有限,本博客的证明可能存在不正确的地方,欢迎大家加我的QQ给予指教。

    qq:2465806616

    参考博客:

    https://blog.csdn.net/qq_41695941/article/details/83025188

    https://blog.csdn.net/noiau/article/details/72514812

  • 相关阅读:
    Coursera机器学习week11 单元测试
    关于 TypeReference 的解释
    getModifiers 方法解释。
    instanceof isInstance isAssignableFrom 比较
    elasticsearch 基础 语法总结
    kibana 启动 关闭 和进程查找
    MD5 SHA1 SHA256 SHA512 SHA1WithRSA 的区别
    spring boot 项目 热启动
    java zip 压缩文件
    Packet for query is too large (1660 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
  • 原文地址:https://www.cnblogs.com/cglongge/p/9451161.html
Copyright © 2011-2022 走看看