由于最近课设要用动态规划,翻阅资料学习一下。
动态规划
解决复杂问题的方法,把它们分解成更简单的子问题。
一旦我们看到一些例子,这个定义就有意义了。实际上,我们今天只看解问题的例子
解决DP问题的步骤
1. 定义子问题
2. 写出与子问题相关的递归式
3.识别并解决基本案例
每一步是非常重要的!!!
一维DP的例子
题目:给定n,找出几种不同的写法
n是1 3 4的和
例子:n = 5,答案是6
◮定义子问题
设Dn为n的个数,表示为1、3、4的和
◮发现规律
-考虑一个可能的解决方案n = x1 + x2 +···+ xm
-如果xm = 1,其余项之和必须为n - 1
-因此,以xm = 1结束的和的数目等于
Dn−1
-考虑其他情况(xm = 3, xm = 4)
◮找到规律
Dn = Dn - 1 + Dn - 3 + Dn - 4
◮解决基本情况
- D0 = 1
- Dn = 0对于所有负n
-或者,可以设置:D0 = D1 = D2 = 1, D3 = 2
◮我们基本上完成了!
实现
很短的!
◮扩展:解决这个巨大的n, n≈1012
-回想斐波那契数列的矩阵形式
Example--POJ 2663: Tri Tiling(完美覆盖)
给定n,找出填满3×n块黑板的方法
多米诺骨牌
◮n = 12一个可能的解决方案
◮定义子问题
-定义Dn为平铺3×n块板的方法数
◮发现规律
定义子问题
◮显然,前面的定义并没有很好地工作
◮Dn的关系并不简单
◮如果我们引入更多的子问题呢?
发现规律
考虑填充第n列的不同方法
-看看剩下的形状是什么
◮练习:
-求An, Bn, Cn的递归式
-只是为了好玩,为什么 Bn 和 En 总是零?
可拓性:求解n×m网格,其中n较小,如n≤10
-我们应该考虑多少个子问题?
二维DP的例子
◮问题:给定两个字符串x和y,找出最长公共
子序列(LCS)并打印其长度
◮例子:
- x: ABCBDAB
- y: BDCABC
-“BCAB”是两个序列中发现的最长子序列,因此
答案是4
解决LCS问题
定义子问题
-令Dij为x1的LCS的长度…我和y1…j
◮发现规律
-如果xi = yj,它们都对LCS有贡献
◮Dij Di =−1, j−1 + 1
-否则,xi 或 yj 都不会对LCS有贡献,所以
一个可以放下
◮Dij = max {Di−1 j Di, j−1}
-找到并解决基本情况:Di0 = D0j = 0
实现
间隔DP的例子
问题:给定一个字符串x = x1…n,求最小值
需要插入的字符,使其成为回文
◮例子:
- x: Ab3bd
-可以得到“dAb3bAd”或“Adb3bdA”插入两个字符
(一个d,一个A)
◮定义子问题
-令Dij为所需的最小字符数
插入使xi…j变成回文
◮发现规律
-考虑一个最短的回文y1…包含xi…j k
- y1 = xi或yk = xj(为什么?)
- y2…k - 1是xi+1的最优解。j或喜…j−1或
11 + 1 j−1
◮最后一例可能只有 y1= yk = xi = xj
◮找到规律
◮找到并解决基本情况:对于所有的i
Di,i = Di,i−1 = 0
◮D的条目必须 j−i 递增的顺序填写
注意,我们如何使用附加变量t以正确的顺序填充表
for循环可以处理多个变量
另一种解决方案
◮反向x 得到x^R
答案是n - L,其中L是LCS (x, x^R)的长度
◮练习:想想为何如此?
树DP的例子
问题:给定一棵树,在不给相邻节点着色的情况下,将尽可能多的节点着色为黑色
◮子问题:
-首先,我们任意确定根节点r
- Bv:以v为根的子树的最优解,其中我们将v涂成黑色
- Wv:以v为根的子树的最优解
-答案是max{Br, Wr}
◮发现规律
-关键观察:一旦确定v的颜色,就可以独立求解子树
-如果v是有色的,它的子元素不能是有色的
如果v没有颜色,它的子元素可以有任何颜色
基本情况:叶节点
DP子集的例子
问题:给定一个有n个节点的加权图,找出访问每个节点一次的最hortest路径(旅行商问题)
◮等等,这不是一个np难的问题吗?
-是的,但是我们可以在O((n^2)*(2^n))时间内解出来
-注意:蛮力算法需要O(n!)时间
◮定义子问题
- DS,v:访问集合S中每个节点一次并以v结束的最优路径的长度
-大约有n*(2^n)个子问题
-答案是,其中V是给定的节点集
◮让我们先解决基本情况
-对于每个节点v, D{v},v = 0
◮发现规律
-考虑一个路径,该路径访问S中的所有节点一次,并在v处结束
-在到达v之前,路径来自S - {v}中的某个u
-该子路径必须是覆盖S - {v}、以u结尾的最优路径
-我们只是尝试所有可能的候选值为 u
使用子集
◮使用子集时,最好有一个好的集表示
◮理念:用一个整数来表示一组
-小整数子集的简洁表示{0,1,…}
-如果第i(最小有效)位是1,则i在集合中
如果第i位是0,i不在集合中
-例如,19 = 010011(2)在二进制中表示一个集合{0,1,4}
使用位掩码
◮x 和 y 并集:x | y
◮交集: x & y
◮对称差集:x ˆ y
◮单集{i}: 1 << i
◮条件测试:x & (1 << i) != 0
总结
Wikipedia定义:“通过将复杂问题分解为更简单的子问题来解决复杂问题的方法”
-现在明白了吗?
◮记住三个步骤!!!
1. 定义子问题
2. 发现规律
3.解决基本情况
以上的例子可以让我们更好的理解如何求解 动态规划问题,更好的理解算法思想。
原文地址: Jaehyun Park -- CS 97SI -- Stanford University
例题集:GeeksforGeeks
其他文献:Dynamic Programming