初识动态规划

动态规划作为一类重要的算法问题,但在日常普通的编程中一般不会见到,大学课程中的数据结构与算法课也不会详细讲解,但是对于很多oj题目中是必备的知识。

动态规划看名字让人摸不着头脑。我最初对其的了解来自于老师在求“斐波那契数方法中非递归解法”稍微的一提,老师当时是说:对于已经计算出的结果,把它存下来为以后使用。

这个想法在求斐波那契数列时自然十分好理解,然而其运用于其他问题时,方法却没有那么明显易懂。

下面以一个运用动态规划的简单例子:求最大连续子序列

给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20。现在增加一个要求,即还需要输出该子序列的第一个和最后一个元素。

此题的动态规划解法即是:设数组max_end_of_i,使max_end_of_i[i]为以第i个元素为结尾的最大连续子序列和,则max_end_of_i[0]即为地0个元素值;

此刻我们使用较为熟悉的递归算法思想:max_end_of_i[i]要么等于max_end_of_i[i-1]+第i个元素值,要么等于第i个元素值(两种情况较大的那个值);

因此以i=1~K-1的顺序我们依次可求得整个max_end_of_i数组;则max_end_of_i数组中最大值即为答案。

其中使用递归思想的那一步使用的递推方式叫做状态转移方程

那么动态规划和递归有何异同呢?

相同点:都使用递推公式

不同点:

1.递归使用递推公式时是以新的参数调用自身由上到下),动态规划则一般是配合一个数组由下到上)求得结果;

2.动态规划以空间换时间,使得算法执行时间复杂度比较低,而递归一般比较耗时。

下面以另一个更复杂些的动态规划问题——01背包问题作为结尾:

有N件物品和一个容量为V的背包。第i件物品的重量是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。每种物品仅有一件,可以选择放或不放

解法:此问题较上一个问题多了一个因素,因此设f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。状态转移方程便 是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}。即:前i件物品放入容量为v的背包可以获得的最大价值等于 max{前i-1件物品放入容量为v的背包可获得的最大价值,前i-1件物品放入容量为v减去第i件物品重量的背包,再加上第i件物品价值}。

这里还可以将空间复杂度从O(N*V)优化为O(V),原理很简单。

posted @ 2012-02-06 10:19  yhchuan  Views(1648)  Comments(2Edit  收藏  举报