您的位置:首页 > 其它

对动态规划和贪心算法的一点理解

2007-08-31 21:15 260 查看
一直很模糊的感觉这两个重要的算法应该有些联系。首先都是求解最优问题的很有效的方法,其次都有明显的最优判定:通过对某些值的MAX和MIN 运算来决定下一步的步骤。具体的异同自己就说不清楚了,关键是对动态规划算法本身也不是特别理解。今天看了一下MIT的算法导论的相关章节,算是有了个大 概认识。
(题外话:算法导论看得不多,但只就这两章而言,可以看出这本教材和国内的算法教材大不一样。国内的教材很多都直接的“由易而难”先介绍贪心然 后介绍动态规划,感觉似乎有很重的“竞赛”气息。而算法导论是先介绍动态规划,再介绍贪心,从学术的角度考虑,动态规划是基础而贪心是特例,这么说来,似 乎国内的教材过于功利化,而缺少纯理论上的培养价值。)
求最优解的问题,从根本上说是一种对解空间的遍历。最直接的暴力分析容易得到,最优解的解空间通常都是以指数阶增长,因此暴力穷举都是不可行的。
最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,如上面的分析,这是不可行的。
贪心和动态规划本质上是对子问题树的一种修剪。两种算法要求问题都具有的一个性质就是“子问题最优性”。即,组成最优解的每一个子问题的解,对 于这个子问题本身肯定也是最优的。如果以自顶向下的方向看问题树(原问题作根),则,我们每次只需要向下遍历代表最优解的子树就可以保证会得到整体的最优 解。形象一点说,可以简单的用一个值(最优值)代表整个子树,而不用去求出这个子树所可能代表的所有值。
动态规划方法代表了这一类问题的一般解法。我们自底向上(从叶子向根)构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中 的最优值作为自身的值,其它的值舍弃。动态规划的代价就取决于可选择的数目(树的叉数)和子问题的的数目(树的节点数,或者是树的高度?)。
贪心算法是动态规划方法的一个特例。贪心特在,可以证明,每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需 要知道一个节点所有子树的情况,就可以求出这个节点的值。通常这个值都是对于当前的问题情况下,显而易见的“最优”情况。因此用“贪心”来描述这个算法的 本质。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。这样,与动态规划相比,它的代 价只取决于子问题的数目,而选择数目总为1。

背包问题

以背包问题为例。贪心算法的思路是,直接选择当前价格/重量比最大的物品放入背包,力图保持背包内的物品的总的价格/重量比总是最大的,以得到 最优的值。动态规划的思路是,对于每一种物品,都要考虑“放它”和“不放它”两种情况,并取最优的一种作为解。动态规划对解空间的遍历要比贪心完全。
显然,如果能保证背包总是满的,则贪心算法是正确的。但0-1背包问题不能保证背包总是满的,这样就降低了整体背包的价格/重量比。这种情况,就只能用动态规划来解。
感觉背包问题似乎是个特例,问题当前的状况(剩余的物品)就可以决定当前的选择,但其它的限制(背包的总重量)使得贪心是错误的。

其余的问题,如矩阵连乘,子串匹配等,则显然不具备贪心的要求,只能用动态规划来解。

另一个问题:背包问题是NP完全问题吗

推荐一个网站:http://www.answers.com,集合了非常棒的定义、资料,下面的文字出自这个网站。
背包问题的动态规划解法是一个“伪多项式阶”算法。如果总重量的整数值c作为规模,它是多项式阶的(O(nc))。而如果用c的二进制位数作为 规模,则它是指数阶的。因此,最优形式解形式(optimization)的背包问题仍是一个NP完全问题,但它有伪多项式阶的解。
关于“伪多项式阶”,有一个形象的例子:求整数n的因数。显然至多只要从2~n-1挨个除一遍就可以得到所有的因数,似乎这是O(n)阶的,但其实若从n的位数来考虑,它就成为了指数阶而变得不可求解。这恰巧就是现在网络加密算法的基础。
而背包问题的判定形式(decision)则是真正的NP完全问题:
对于一组物品,给定价值和重量,在满足重量限制的前提下,能否选出物品的一组子集,使得总价值恰好等于某一个给定值C。
这又被称为“子集和(subset sum)”问题。

参考链接:http://www.answers.com/topic/knapsack-problem,以防我理解有误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: