从0-1背包问题到动态规划
来源:互联网 发布:淘宝网天猫电器电油汀 编辑:程序博客网 时间:2024/05/16 15:26
算法——贪心算法解0-1背包问题
局部最优策略(locally optimal decisions,比如贪心算法),并不保证全局最优(global optimums)
“在我的后园,可以看见墙外有两株树,一株是枣树,还有一株也是枣树。”,同样如果有两个手表,为了达到0/1背包问题的要求,也可转化为一个手表,还有一个手表。
brute force(暴力法)的本质是 exhaustive enumeration(穷举法)
一个算法的时间复杂度为指数级时,将会产生十分恐怖的计算量,而动态规划算法可以用来解决指数级时间复杂度的问题,只是说,有些指数级时间复杂度的问题可以通过动态规划算法求解,并非全部。
动态规划(Dynamic programming)核心概念有二:
overlapping subproblems: 重叠子问题
或者说,子问题(subproblems)出现了重叠,子问题的“重叠”意味着计算机的“重复计算”。比如,斐波那契数列的例子不像二分搜索(子问题之间比如独立,也即不存在子问题重叠的问题),可参考 每周一刷——从斐波那契数列到动态规划 。
optimal substructure: 最优子结构
所谓动态规划即是寻找这样的一个最优子结构(substructure),它通过引入 memo 查找表(look-up table)的形式实现对重叠的子问题只进行有限次的计算。也即:record value 1st time,look it up the subsequent times we need it(一次记录,多次使用)
背包问题(knapsack problem)又叫装箱问题(bin packing)。所谓0-1背包问题,对于一件物品要么拿走,要么不拿,不存在拿部分的情况,自然可与二进制对应起来,所谓当物品为
为了实现用动态规划的方法进行背包问题的求解,我们首先来看使用动态规划求解斐波那契数列的问题,关于用动态规划求解斐波那契数列的详细讨论请见 每周一刷——从斐波那契数列到动态规划 。
def fib(n, m): if n not in m: m[n] = fib(n-1, m) + fib(n-2, m) return m[n]if __name__ == '__main__': m = {0:0, 1:1} print([fib(n, m) for n in range(10)]) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
decision tree(决策树)
- weights = [5, 3, 2],三个物品各自的重量;
- values = [9, 7, 8],三个物品各自的价值;
- max = 5,背包的最大承重;
所谓0/1背包问题,也即对每一件物品只有选和不选两种选择,也即分二叉,从当前节点出发,有两个分支。
我们定义如下的树的节点(node)结构:物品的编号
,背包还能容纳的最大重量
,当前背包所放物品的价值
构成的三元组,我们以逆序遍历每件物品,所以根节点结构为:[2, 5, 0]。
def maxVal(i, w, v, c): if i == 0: return v[i] if w[i] <= 0 else 0 without_i = maxVal(i-1, w, v, c) if w[i] > c: return without_i with_i = v[i] + maxVal(i-1, w, v, c-w[i]) return max(without_i, with_i)if __name__ == '__main__': weights = [5, 3, 2] values = [9, 7, 8] n, c = len(weights), 5 print(maxVal(n-1, weights, values, c))
上例中的重叠子问题(overlapping subproblem)还不明显,当物品较多时,画出其决定树,便会出现大量的重叠子问题,又因为weights
和values
是固定不变的,真正变化的是物品编号以及当前背包还能容纳的物品重量。
def fastMaxVal(i, w, v, c, m): try: return m[(i, c)] except KeyError: if i == 0: if w[i] <= c: m[(i, c)] = v[i] return m[(i, c)] m[(i, c)] = 0 return 0 without_i = fastMaxVal(i-1, w, v, c, m) if w[i] > c: m[(i, c)] = without_i return m[(i, c)] with_i = v[i] + fastMaxVal(i-1, w, v, c-w[i], m) m[(i, c)] = max(with_i, without_i) return m[(i, c)]if __name__ == '__main__': ws = [5, 3, 2] vs = [9, 7, 8] n, c = len(ws), 5 m = {} print(fastMaxVal(n-1, ws, vs, c, m))
- 从0-1背包问题到动态规划
- 【动态规划】从子集和问题到背包问题
- 从01背包问题走进动态规划
- 从01背包问题理解动态规划
- 从01背包问题理解动态规划
- 0/1背包问题动态规划详解
- 动态规划解0-1背包问题
- 0/1背包问题动态规划详解
- 动态规划 ------0-1背包问题
- 0/1背包问题动态规划详解
- 动态规划解决0-1背包问题
- 0/1背包问题动态规划详解
- 0-1背包问题--动态规划解法
- 动态规划解0-1背包问题
- 0-1背包问题动态规划
- 0-1背包问题,动态规划求解
- 动态规划解决0-1背包问题
- 0/1背包问题动态规划详解
- java基础-jdbc
- Linux 引导过程内幕
- MongoDB索引使用
- 国内做“人脸识别”的机构
- 解决Activity启动黑屏及设置android:windowIsTranslucent不兼容activity切换动画问题
- 从0-1背包问题到动态规划
- div 文字自动换行
- Spring:源码解读Spring IOC原理
- [FMS]Flash Media Server4.5(FMS4.5)优化指南说明
- 把自己的Library分享到jCenter和Maven Central的注意事项
- session、cookie概念作用辨析
- 需要搞清楚的一些列表控件
- 下面的两种方法都能够将Sphere变为Cube 父节点元素
- JSP属性范围