打开网易新闻 查看更多视频

动态规划 几个例题:

例一、最长公共子序列(POJ1458) 给出两个字符串,求出这样的一 个最长的公共子序列的长度:子序列 中的每个字符都能在两个原串中找到, 而且每个字符的先后顺序和原串中的 先后顺序一致。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

活学活用 掌握递归和动态规划的思想,解决问题时灵活应用

例二、 Help Jimmy(POJ1661) "Help Jimmy" 是在下图所示的场景上 完成的游戏:

打开网易新闻 查看精彩图片

场景中包括多个长度和高度各不相同的平台。 地面是最低的平台,高度为零,长度无限。 Jimmy老鼠在时刻0从高于所有平台的某处开始下落, 它的下落速度始终为1米/秒。当Jimmy落到某个平台上 时,游戏者选择让它向左还是向右跑,它跑动的速度 也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下 落。Jimmy每次下落的高度不能超过MAX米,不然就 会摔死,游戏也会结束。 设计一个程序,计算Jimmy到地面时可能的最早时间。

输入数据 第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四 个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是 Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行 每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的 高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所 有坐标的单位都是米。

Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边 缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保Jimmy一定 能安全到达地面。

打开网易新闻 查看精彩图片

Jimmy跳到一块板上后,可以有两种选择,向左走,或向右走。 走到左端和走到右端所需的时间,是很容易算的。 如果我们能知道,以左端为起点到达地面的最短时间,和以右端为起点到达 地面的最短时间,那么向左走还是向右走,就很容选择了。 因此,整个问题就被分解成两个子问题,即Jimmy所在位置下方第一块板左端 为起点到地面的最短时间,和右端为起点到地面的最短时间。 这两个子问题在形式上和原问题是完全一致的。将板子从上到下从1开始进行 无重复的编号(越高的板子编号越小,高度相同的几块板子,哪块编号在前无 所谓),那么,和上面两个子问题相关的变量就只有板子的编号。

不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子,假 设LeftMinTime(k)表示从k号板子左端到地面的最短时间, RightMinTime(k)表示从k号板子右端到地面的最短时间,那么, 求板子k左端点到地面的最短时间的方法如下:

打开网易新闻 查看精彩图片

上面,h(i)就代表i号板子的高度,Lx(i)就代 表i号板子左端点的横坐标,Rx(i)就代表i号板 子右端点的横坐标。那么 h(k)-h(m) 当然就是 从k号板子跳到m号板子所需要的时间,Lx(k)- Lx(m) 就是从m号板子的落脚点走到m号板子左端 点的时间,Rx(m)-Lx(k)就是从m号板子的落脚点 走到右端点所需的时间。 求RightMinTime(k)的过程类似。 不妨认为Jimmy开始的位置是一个编号为0,长 度为0的板子,那么整个问题就是要求 LeftMinTime(0)。 输入数据中,板子并没有按高度排序,所以程 序中一定要首先将板子排序。

时间复杂度: 一共 n个板子,每个左右两端的最小时间各算 一次 O(n) 找出板子一段到地面之间有那块板子,需要遍 历板子 O(n) 总的时间复杂度O(n2)

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

例三、最佳加法表达式:

有一个由1..9组成的数字串.问如果将m个加 号插入到这个数字串中,在各种可能形成的 表达式中,值最小的那个表达式的值是多少。

解题思路:

假定数字串长度是n,添完加号后,表达式的最后 一个加号添加在第 i 个数字后面,那么整个表达 式的最小值,就等于在前 i 个数字中插入 m – 1 个加号所能形成的最小值,加上第 i + 1到第 n 个数字所组成的数的值(i从1开始算)。

设V(m,n)表示在n个数字中插入m个加号所能形成 的表达式最小值,那么: if m = 0 V(m,n) = n个数字构成的整数 else if n < m + 1 V(m,n) = ∞ else V(m,n) = Min{ V(m-1,i) + Num(i+1,n) } ( i = m … n-1) Num(i,j)表示从第i个数字到第j个数字所组成的数。数字编号从1开始算。此操 作复杂度是O(j-i+1) 总时间复杂度:O(mn2 ) 。

例四、滑雪(百练1088) Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。 可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底, 你不得不再次走上坡或者等待升降机来载你。 Michael想知道载一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字 代表点的高度。下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子 中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最 长的一条。输入输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行, 每行有C个整数,代表高度h,0<=h<=10000。输出输出最长区域的长度。

打开网易新闻 查看精彩图片

解题思路:

L(i,j)表示从点(i,j)出发的最长滑行长度。 一个点(i,j), 如果周围没有比它低的点,L(i,j) = 1 否则 递推公式: L(i,j) 等于(i,j)周围四个点中,比(i,j)低,且L值最大的那个点 的L值,再加1 复杂度:O(n2 )

解法1) “人人为我”式递推 L(i,j)表示从点(i,j)出发的最长滑行长度。 一个点(i,j), 如果周围没有比它低的点,L(i,j) = 1 将所有点按高度从小到大排序。每个点的 L 值都初始化为1 从小到大遍历所有的点。经过一个点(i,j)时,用递推公式求L(i,j)

解法2) “我为人人”式递推 L(i,j)表示从点(i,j)出发的最长滑行长度。 一个点(i,j), 如果周围没有比它低的点,L(i,j) = 1 将所有点按高度从小到大排序。每个点的 L 值都初始化为1 从小到大遍历所有的点。经过一个点(i,j)时,要更新他周围的,比它高的点 的L值。例如: if H(i+1,j) > H(i,j) // H代表高度 L(i+1,j) = max(L(i+1,j),L(i,j)+1)