# 以计算斐波那契数列为例说说动态规划算法（Dynamic Programming Algorithm Overlapping subproblems Optimal substructure Memoization Tabulation）

（注：背包问题分为两种：若物体不可分割，则称为0-1背包问题，比如拿一块金砖；若物体可以分开，则称为一般背包问题，比如拿多少克大米。一般背包问题可以用贪心算法解决。贪心算法在每个阶段即可找出当前最优解，每个阶段的最优状态都是由上一个阶段的最优状态得到的。）

1）重叠子问题（Overlapping Subproblems）：有些子问题会被重复计算多次。

2）最优子结构（Optimal Substructure）：问题的最优解可以从某个子问题的最优解中获得。

                         fib(5)
/             \
fib(4)                fib(3)
/      \                /     \
fib(3)      fib(2)         fib(2)    fib(1)
/     \        ¦              ¦          ¦
fib(2)   fib(1)      1              1          1
¦        ¦     1        1

def fib(n):
print("fib called with",n)  #看调用了哪个fib函数，也就是说看计算了斐波那契数列的第几项
if n<2:
return n
else:
return (fib(n-1) + fib(n-2))

print(fib(5))

fib called with 5
fib called with 4
fib called with 3
fib called with 2
fib called with 1
fib called with 0
fib called with 1
fib called with 2
fib called with 1
fib called with 0
fib called with 3
fib called with 2
fib called with 1
fib called with 0
fib called with 1
5

def fastFib(n,memo):  #memo是设置的一个字典
print("fib1 called with",n)
if not n in memo:  #如果斐波那契数列的第n项数值不在字典里，那么用递归方式计算该值，并把该值放入字典中
memo[n]=fastFib(n-1,memo)+fastFib(n-2,memo)
return memo[n]   #如果斐波那契数列的第n项数值在字典里，那么直接返回字典里的该项数值

def fib1(n):
memo={0:0,1:1}  #初始化一个字典
return fastFib(n,memo)

fib1 called with 5
fib1 called with 4
fib1 called with 3
fib1 called with 2
fib1 called with 1
fib1 called with 0
fib1 called with 1
fib1 called with 2
fib1 called with 3
5

1) 默记法（从上到下）/ Memoization (Top Down)：设置一个数组，当需要子问题的解时，先去这个数组中查找。如果此问题之前已经求过解，那么就直接返回该值，如果此问题之前并未求过解，那么就计算该值并把结果放入数组中，以备后用。

2) 表格法（从下到上）/ Tabulation (Bottom Up)：用迭代法建立一个表格，从该表格中返回所需的值。

posted @ 2017-11-29 16:46  HuZihu  阅读(1892)  评论(0编辑  收藏