这里主要是较为详细地理解动态规划的思想,思考一些高质量的案例,同时也响应如下这么一句口号:

“迭代(regression)是人,递归(recursion)是神,动态规划是what?”

Video series for Dynamic Programming


 

Planning a company party

Ref: http://mypathtothe4.blogspot.com.au/2013/03/dynamic-programming-company-party.html

Stewart教授是一家公司总裁的顾问,这家公司计划一个公司聚会。这个公司有一个层次结构;也就是,管理关系形成一棵以总裁为根的树。人事部给每个雇员以喜欢聚会的程度来排名,这是一个实数。为了使每个参加者都喜欢这个聚会,总裁不希望一个雇员和他(她)的直接上司同时参加。

生成一张客人列表,使得客人喜欢聚会的程度的总和最大。

Naive Recursive Solution

Idea 1

    1. 变成了从大集合中挑N个人组合,当然,最好是由多到少的选人。
    2. 然后判断这个集合是否满足情况。

Idea 2

Find-Max-Conv(Node n)
if n.children = null
return max(, n.rating)

return max( Sum(Find-Max-Conv(i)) for all i = n.children),
Sum(Find-Max-Conv(i) for all i = n.grandchildren) + n.rating) //return 的内容有问题,不过不要紧

Let's take a quick look at what this recursion does: the base case (leaves) in lines (1, 2) simply returns the max value of not 0 (not inviting someone) and the conviviality rating of the person. (We need the comparison with 0 in case the conviviality is negative). Line 3 is our recursive call; the solution, given some node, will be the maximum of inviting the current node (person) and not inviting the current node (person). If we invite the current node, we cannot invite children, and thus we sum the current value with the maximum ratings of the current node's grandchildren. If we don't invite the current node, then the maximum value would be the sum of maximum convivialities over all children.

Consider the running time of this algorithm. We go through every node in the tree, and consider adding or not adding it. So there are two options for each of n nodes (0, 1), meaning the number of operations will be some function of 2^n. This is exponential running time and undesirable.

Dynamic Programming

如何寻找sub-problem。

The principal idea then, is to start from node n and work back to the root, each time basing the current optimal conviviality on previously computed sub-problems that have been stored in some memoization table.

Find-Max-Conv(Tree t)
Let MC[ ] be an array of length n that contains max conviviality from this node down in the tree
for i = Node n down to
MC[i] = max(i.rating + Sum of all MC[i.grandchildren], Sum of all MC[i.children])
(If node i has no grandchildren or children, replace i.grandchildren and/or i.children with )
return MC[]

寻找子问题

节点(青绿)不参加的话,孩子都能参加。那么孩子的高兴值在sub-problem中应该是计算过了,保存在MC[]中。

节点(暗灰)若参加的话,孩子不能参加。那么孙子的高兴值在sub-problem中应该是计算过了,保存在MC[]中。

计算n个节点的SelectRoot和UnselRoot,每次计算都只使用子节点的域值,所以整个计算的过程也只累加了树中除了根的其它节点的域值(每个节点就被用一次)。所以算法复杂度为O(n)。

Find if a string is interleaved of two other strings

Ref: http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-interleaving-of-two-other-given-strings-set-2/

For example A = “XXY”, string B = “XXZ” and string C = “XXZXXXY”

两个字符串交叉得到的字符串,其中隐含了"顺序性"

Naive Recursive Solution

以下方式相当于遍历完了所有情况,有点围棋穷举的意思。

// A simple recursive function to check whether C is an interleaving of A and B
bool isInterleaved(char *A, char *B, char *C)
{
// Base Case: If all strings are empty
if (!(*A || *B || *C))
return true; // If C is empty and any of the two strings is not empty
if (*C == '\0')
return false; // If any of the above mentioned two possibilities is true,
// then return true, otherwise false
return ( (*C == *A) && isInterleaved(A+, B, C+))
|| ((*C == *B) && isInterleaved(A, B+, C+));
}

The worst-case time complexity of the recursive solution is O(2n).  // 从return的形式可见"二叉树的node的扩展方式"

The above recursive solution certainly has many overlapping subproblems. For example, if we consider A = “XXX”, B = “XXX” and C = “XXXXXX” and draw recursion tree, there will be many overlapping subproblems.
Therefore, like other typical Dynamic Programming problems, we can solve it by creating a table and store results of subproblems in bottom up manner.

Dynamic Programming

Algorithm:

s1 = “aabcc”       <- x
s2 = “dbbca”       <- y
s3 = “aadbbcbcac”  <- z

寻找子问题

理解:

当len z = 4时,只会是len x + len y = 4的情况;

那么,这些情况中的一些,是在sub-problem中解决了的;

在表格中,只需关心“子问题”为T的格子,以及临近的两个格子(右,下)。

Idea:

在已有的可以的情况下的头顶加一个合格的帽子是没问题的。

不影响sub-problem的内部合理性,帽子也是满足

"If z is the interleaving of x and y, it contains a subproblem z'= z1...zm+n−1 and the last bit zm+n must be xm or yn."

len z = 4时(黄色格子),sub-problem的结果就是桔黄色的格子如下。

进一步地,规律如下,T的方格构成的必须是连通图。

Weights and Measures - Turtle Tower

叠乌龟问题:极其经典,研究价值五星 - 你值得拥有! - 因为五星,所以配图。

From: http://cgi.cse.unsw.edu.au/~cs3121/Lectures/COMP3121_Lecture_Notes_DP.pdf

You are given n turtles, and for each turtle you are given its weight and its strength.

The strength of a turtle is the maximal weight you can put on it without cracking its shell.

Find the largest possible number of turtles which you can stack one on top of the other without cracking any turtle.

Naive Recursive Solution

  /* 非常复杂,不太现实 */

Dynamic Programming

Subproblem P(j): Find the largest possible number of turtles from the set {T1 , . . . , Tj } 
which you can stack one on top of the other without cracking any turtle.

常规"子问题"没办法迭代!

思考:10个龟情况下的叠起来的方案,能否用于加了一个11th龟后的情况?

P(11) 的所有子情况是:

    • P(10)的最优解
    • P(09)的最优解
    • ...
    • P(01)的最优解

那么,P(11) 能利用这些么?

    • new P(11)的最优解中T11是最下面的位置么?
    • new P(10)的最优解中T11是最下面的位置么?
    • new P(09)的最优解中T11是最下面的位置么?
    • ...
    • new P(01)的最优解中T11是最下面的位置么?

不能保证!

加一个“龟”,会破坏子问题的situation,导致必须重新思考“子问题”

故,new P(09)的最优解就不是extension of P(09) 的最优解。

如何找到正确的“子问题”

那什么feature才能保证永远在最优方案最下面的位置呢?

(推理一)

Answer: strength + weight

Thus, we order turtles according to the sum of their strength plus their weight, i.e., assume that for all i, j ≤ n

关于这个意义在于,它保证了一种叠海归的方案,这个方案的最底下的海龟是新海龟,因为它的strength + weight最大。

本就是按照有小到大的顺序依次处理的嘛。更直接地说:Tj相对于已有在处理的海龟集都是最大的。

也就是说:子问题扩展的时候,提供了一种安全的“添加一个海龟”的顺序。

感性理解

To guarantee that optimal towers can be obtained from the previous optimal towers

we build a sequence of lightest possible towers of every possible height.

P(10) height:3 的构造过程:

        

T10 若能承受w1+w2,则T10必定在最底下。     <-- 保证了recursion的可行性!

T10 不能承受w1+w2,则不管如何排1,2,T10 都是不可能的。

假设,1,2都是只能承受一个node的主儿,那么height:3时,就会是右图所示,去掉了2。

Key理解:

"在P(10) height:3可行的大前提下,如此,必定真正的P(10) height:3就是这么组合的了"

何为"可行"?就是直接看sT10 > w1+w2就是可行。(因为有推理一作为保证)

P()  // Now

      • height 1  --> 若干results, 只选最轻的那一个
      • height 2  --> 若干results, 只选最轻的那一个
      • height 3  --> 若干results, 只选最轻的那一个
      • ...
      • height 10 --> 若干results, 只选最轻的那一个

P()  // Sub-problem

      • height 1 --> 若干results, 只选最轻的那一个
      • height 2 --> 若干results, 只选最轻的那一个
      • height 3 --> 若干results, 只选最轻的那一个
      • ...
      • height 9 --> 若干results, 只选最轻的那一个

etc.

Thus, we solve the following generalisations of our problem, for every j ≤ n:

Subproblem P(j):

For each k ≤ j for which there exists a tower of turtles of length k built from turtles {T1, . . . , Tj} (not necessarily containing Tj ),

find the lightest one.

Recursion:

With this subproblem, we can solve any P(i) like this:  // P(10)

*************************************************************

To obtain the lightest tower θ(k, i) of any height k built from turtles {T1,...,Ti},  // θ(k, 10): P()下的一系列heigh k = 3

we look at

    • the lightest tower θ(k, i−1) of height k                                                               // θ(k, 09): P()下的一系列heigh k = 3

    • the lightest tower θ(k-1, i−1) of height k − 1                                                     // θ(k, 09): P()下的一系列heigh k-1 = 2

both built from turtles T1,T2,...,Ti−1, which we have got in the sub-problem P(i-1).

*************************************************************

有了已解决的子问题,那么,咱们就开始判断咯:

    • If the tower obtained by extending θ(k-1, i−1) with Ti is both legitimate and lighter than θ(k, i−1), we let θ(k, i) be such a tower. (this means Ti contributes to a better lightest tower with more Residual Capacity)

    • Otherwise we let θ(k, i) = θ(k, i−1).

可以如此理解:

  新转来一名学生,只要比较她跟班里的第三名成绩就好了:

  * 比第三名好的话,就拿前两名加这个新生构成新的top3;

  * 没第三名好的话,原来的top3依然保留地位。

Finally, we obtain the lightest tower θ(k, i) of any height k for P(i).

The solution to our problem is now obtained from the solution to P(n) by picking the longest tower obtained by solving P(n).

Box Stacking Problem

video讲解:https://people.cs.clemson.edu/~bcdean/dp_practice/dp_5.swf

The Box Stacking problem is a variation of LIS problem. We need to build a maximum height stack.

Following are the key points to note in the problem statement:

1) A box can be placed on top of another box only if both width and depth of the upper placed box are smaller than width and depth of the lower box respectively.

2) We can rotate boxes. For example, if there is a box with dimensions {1x2x3} where 1 is height, 2×3 is base, then there can be three possibilities, {1x2x3}, {2x1x3} and {3x1x2}.

3) We can use multiple instances of boxes. What it means is, we can have two different rotations of a box as part of our maximum height stack.

Following is the solution based on DP solution of LIS problem.

1) Generate all 3 rotations of all boxes. The size of rotation array becomes 3 times the size of original array. For simplicity, we consider depth as always smaller than or equal to width.

2) Sort the above generated 3n boxes in decreasing order of base area.

3) After sorting the boxes, the problem is same as LIS with following optimal substructure property.

MSH(i) = Maximum possible Stack Height with box i at top of stack  // 这个顶上的 box i 是强制安排的

MSH(i) = { Max ( MSH(j) ) + height(i) } , where j < i and width(j) > width(i) and depth(j) > depth(i).

If there is no such j then MSH(i) = height(i)

4) To get overall maximum height, we return max(MSH(i)) where 0 < i < n

Bin-packing problem

传统的三种方式:https://www.youtube.com/watch?v=kiMFyTWqLhc

Full-bin packing Algorithm中已体现出了动规的影子,或者叫必要性。

要确保得到最优的答案,还得看动规,以下是一些可能有用的参考链接。

ref: https://www.youtube.com/watch?v=wy45-JH8_yY

ref: http://www.sciencedirect.com/science/article/pii/S0377221706004310?via%3Dihub

Idea: (核心思想)

opt(i, j, p)是由一堆子问题堆积起来的,or 推起来的。

关键在于理解这个opt(i, j, p)和下面子问题之间的关系,要如何建立之间的逻辑关系。

子问题:

条件: s1 = 2,  s2 = 3,  s3 = 5,  C = 10 (size of bin)

i = 7, j = 3, p = 3  
opt(i-5, j, p) opt(i-3, j-1, p) opt(i-2, j-2, p) opt(i, j-3, p) opt(i-2, j, p-1) opt(i-1, j-2, p-1) opt(i, j, p-2)  
opt(2, 3, 3) = 3 4, 2, 3 5, 1, 3 7, 0, 3 5, 0, 2 6, 1, 2

7, 7, 0

sub-p
  opt(0,1,3) = 2 bin 2,0,3 0,3,2 1,1,2 2,3,1 sub-p of 2,3,3
           

opt(0,1,1) = 1 bin

sub-p of 0,1,3

size: 2*2+3*3+3*5=28

暗含了一个道理:

多两个s1和两个s2是肯定要

多一个bin的

 

size: 0*2+1*3+3*5=18

暗含了一个道理:

多两个s3是肯定要多一个bin的

         

可见,这是个六叉树!孩子就是子问题。

递归是从上到下,貌似预分配了所需的所有空间,也就是六叉树的所有node。

动规,则提供了自底向上的思路,每个子问题仅保存了最优的结果(一个数值),这样便节省了空间。

其实,这也体现了 prolog language 解决问题的思路,以及设计原理,即:

解决递归问题,选择prolog会更加高效,方便。

IDE online: http://potassco.sourceforge.net/clingo.html


[Optimization] Advanced Dynamic programming的更多相关文章

  1. Dynamic Programming: From novice to advanced

    作者:Dumitru 出处:http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg An impo ...

  2. Bayesian Optimization with a Finite Budget: An Approximate Dynamic Programming Approach

    目录 概 主要内容 Lam R, Willcox K, Wolpert D H, et al. Bayesian Optimization with a Finite Budget: An Appro ...

  3. [Optimization] Dynamic programming

    “就是迭代,被众人说得这么玄乎" “之所以归为优化,是因为动态规划本质是一个systemetic bruce force" “因为systemetic,所以比穷举好了许多,就认为是 ...

  4. 最优化问题 Optimization Problems & 动态规划 Dynamic Programming

    2018-01-12 22:50:06 一.优化问题 优化问题用数学的角度来分析就是去求一个函数或者说方程的极大值或者极小值,通常这种优化问题是有约束条件的,所以也被称为约束优化问题. 约束优化问题( ...

  5. 动态规划 Dynamic Programming

    March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...

  6. [算法]动态规划(Dynamic programming)

    转载请注明原创:http://www.cnblogs.com/StartoverX/p/4603173.html Dynamic Programming的Programming指的不是程序而是一种表格 ...

  7. Julia is a high-level, high-performance dynamic programming language for technical computing, with syntax that is familiar to users of other technical

    http://julialang.org/ julia | source | downloads | docs | blog | community | teaching | publications ...

  8. Algo: Dynamic programming

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  9. Dynamic Programming

    We began our study of algorithmic techniques with greedy algorithms, which in some sense form the mo ...

随机推荐

  1. python 字符串的一些方法

    总结:# split 分割 ********# strip 脱 默认脱头尾的空格 ********# replace 替换 ********# join 插入 拼接 ********# format ...

  2. WordPress主题开发:输出指定页面导航

    实例: <ul> <li class="widget widget_nav_menu"> <?php if(is_page(array(12,14,1 ...

  3. .Net Core Md5加密整理

    一..Net Core中Md5使用说明 .Net Core中自带Md5加密处理,使用方法和 .Net Framework中相同 所在命名空间 using System.Security.Cryptog ...

  4. hive中 regexp_replace的用法,替换特殊字符问题

    数据仓库中有的字段不合格,有特殊字符,比如换行符. poi_name \n19013 \n12013 怎么把换行符替换掉呢? https://cwiki.apache.org/confluence/d ...

  5. C#代码安装Windows服务

    using System;using System.Collections.Generic;using System.ServiceProcess;using System.Configuration ...

  6. 微软BI 之SSAS 系列 - 多维数据集维度用法之一 引用维度 Referenced Dimension

    在 CUBE 设计过程中有一个非常重要的点就是定义维度与度量值组关系,维度的创建一般在前,而度量值组一般来源于一个事实表.当维度和度量值组在 CUBE 中定义完成之后,下一个最重要的动作就是定义两者之 ...

  7. VTK拾取网格模型上的可见点

    消隐与Z-Buffer 使用缓冲器记录物体表面在屏幕上投影所覆盖范围内的全部像素的深度值,依次访问屏幕范围内物体表面所覆盖的每一像素,用深度小(深度用z值表示,z值小表示离视点近)的像素点颜色替代深度 ...

  8. JAVA分库分表的实现方案

    分库分表的实现方案无非2种:1.本地,2.远程.而在本地一般有2种实现(1.业务代码级别   2.jdbc级别), 其中jdbc级别的本地代理方案的代表有:当当开源的 shardingsphere,远 ...

  9. iOS 7设计备忘单

    With the release of iOS 7, app designers and developers will need to adjust their visual language to ...

  10. 动态改变APP图标

    一.iOS动态更换App图标(一):基础使用 该功能应用的场景 1.白天/夜间模式切换,在切换App主色调同时切换App图标. 2.各类皮肤主题(淘宝就可换肤),附带App图标一块更换. 3.利用Ap ...