![e403617614354e08304d815edb21b4d8.png](https://img-blog.csdnimg.cn/img_convert/e403617614354e08304d815edb21b4d8.png)
回顾
再来回顾一下背包问题,背包问题是一个典型的组合问题,目标是让我们在容量为
![b23f05cdb2d53f20469b7e380016d6aa.png](https://img-blog.csdnimg.cn/img_convert/b23f05cdb2d53f20469b7e380016d6aa.png)
如用动态规划来解决背包问题,事情就会变得简单得多。这里我们用两种方式来实现:自底向上(bottom-up)和自顶向下(top-down)。两者的区别可以这样来理解,假设我们需要用一些零件来拼接一件工艺品,自底向上就好比一名技术精湛的工人,虽然他不知道最后这些零件要拼出一件什么东西,但他深知这些零件的构造,熟悉拼接过程中的顺序,因此如果他一直重复拼接的过程就能最终拼出一件工艺品,因此自底向上用到的最多的方法是迭代;而自顶向下则好似一名工程师,他有一张该工艺品的设计图纸,懂得每一部分的具体功能,并且细分至零件,最后根据这张图纸将它们拼接起来,因此自底向上用到的最多的方法是递归。有同学就会问了,这和分治有什么区别?答案是当然有,工程师很聪明,因为他从来没有接触过零件的组装,因此每当有一部分零件组装好了之后,它都会拿笔记录下来组装的过程,下次组装相同的零件的时候就会大大缩短所需要的时间。下面我们就来看看这两种方式是如何在背包问题中实现的吧!
![70fef0e636d538a373b39d6114a3e260.png](https://img-blog.csdnimg.cn/img_convert/70fef0e636d538a373b39d6114a3e260.png)
自底向上
我们先来考虑一下背包问题的子问题。假设物品数为
再来说说子问题之间的关系,我们用
![e1fac1eed8b7b7d40aff092dd7e140c3.png](https://img-blog.csdnimg.cn/img_convert/e1fac1eed8b7b7d40aff092dd7e140c3.png)
我们的实例为:
![494136f2296cf6468e5e603b6211788a.png](https://img-blog.csdnimg.cn/img_convert/494136f2296cf6468e5e603b6211788a.png)
随后我们增大
![a17cbe43dd7c0eb2c6c5bdb7021b6904.png](https://img-blog.csdnimg.cn/img_convert/a17cbe43dd7c0eb2c6c5bdb7021b6904.png)
第一行剩下的列我们根据关系式
![91ff05475d4a32aa4869c934f5418d55.png](https://img-blog.csdnimg.cn/img_convert/91ff05475d4a32aa4869c934f5418d55.png)
同理,第二行也是从
![81f2001d0616ef15fc5639b894cf4c19.png](https://img-blog.csdnimg.cn/img_convert/81f2001d0616ef15fc5639b894cf4c19.png)
剩下的列同样也是通过关系式
![ed874756f3366ff44cba0431a7612322.png](https://img-blog.csdnimg.cn/img_convert/ed874756f3366ff44cba0431a7612322.png)
下面的行和列以此类推,直到把整张表填满,最后原问题的最优解为
![2af5be8f000d0d1da63eaf1beed10e58.png](https://img-blog.csdnimg.cn/img_convert/2af5be8f000d0d1da63eaf1beed10e58.png)
像这样,先从最简单的子问题入手,将子问题的解用一张表存储起来,然后后面复杂的子问题是通过前面子问题的解得出的,我们把这种方法叫做自底向上。
def
由于需要用到
自顶向下
自顶向下法又叫做备忘录法,它是基于递归来实现的。首先我们还是需要建一个
![0ab8d002ee1edfb9f29064091f7c3d8a.png](https://img-blog.csdnimg.cn/img_convert/0ab8d002ee1edfb9f29064091f7c3d8a.png)
跟自底向上的方法不同的是,自顶向下着眼于原问题的解,然后通过递归的方式搜索子问题的解,如果子问题没有解(表中对应项为
![5849ef49b0be7271c33d512fd8aadc7a.png](https://img-blog.csdnimg.cn/img_convert/5849ef49b0be7271c33d512fd8aadc7a.png)
然后我们递归地向下搜索,这里即是从
![de95aa3a55e35b1b52f5b13b33784317.png](https://img-blog.csdnimg.cn/img_convert/de95aa3a55e35b1b52f5b13b33784317.png)
![e74eba4c6749e374821a84b3fa2b8513.png](https://img-blog.csdnimg.cn/img_convert/e74eba4c6749e374821a84b3fa2b8513.png)
返回后,在表中记录下相应的最优解,以便后面的子问题使用,最后得到原问题的解。
![2a8b805fcf237ac6957d03c14c5a0737.png](https://img-blog.csdnimg.cn/img_convert/2a8b805fcf237ac6957d03c14c5a0737.png)
这样就完成了自顶向下的全部过程,下面就是用代码来实现它啦~
def
同样,自顶向下解决背包问题的时间和空间复杂度也为
→ 本节全部代码 ←
← 关于钱的两个经典问题 | 算法与复杂度zhuanlan.zhihu.com![0ba86b9b9e8eb7bd7c8dce593a76fbf7.png](https://img-blog.csdnimg.cn/img_convert/0ba86b9b9e8eb7bd7c8dce593a76fbf7.png)
![0ba86b9b9e8eb7bd7c8dce593a76fbf7.png](https://img-blog.csdnimg.cn/img_convert/0ba86b9b9e8eb7bd7c8dce593a76fbf7.png)