动态规划|Dynamic Programming

由于最近课设要用动态规划,翻阅资料学习一下。

动态规划

解决复杂问题的方法,把它们分解成更简单的子问题。

一旦我们看到一些例子,这个定义就有意义了。实际上,我们今天只看解问题的例子

解决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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值