动态规划和子结构的浅谈
1 def fib(n): 2 global numCails 3 numCails +=1 4 print "numCails-->",numCails 5 print "n---->",n 6 if n <=1: 7 return n 8 else: 9 return fib(n-1) + fib(n-2)
我们先看看之前的代码。这是一个 斐波那契数列 我们知道这个代码的执行会有很多重叠的子结构。
让我们先看下图{我今天不用笔画了 LOL}
{感谢ProcessOn,我也能画个能看的图了}
我们从上图看到 产生和很多重叠的子结构,重复运算了很多已经算过了,这就比较尴尬了。
这个时候我们要提下动态规划了:
{个人----理解}
动态规划:动态规划是一种思维方法,也是一种优化原理。优化思路:通过保存那些已经求过值的状态,来避免相同子结构的出现
猿爸爸把 1+1+1+1+1+1+1+1 = 写在纸上,问小猿(咦):
「它们加起来是多少哇?」
(数了一会…)「8 !」
猿爸爸在左边又加了个 1+,再问一次小猿:
「现在呢?」
(迅速地)「9 !」
「为什么小猿这么快就知道了呢?」
「因为你刚刚加了 1 啊~」
「所以只要记得之前的结果,就不用再计一次数啦。」
嗯,动态规划就是一种「先记住些事,方便后面节约时间」的神奇方法
{真是 so easy啊}
我们在看改进过后的代码
1 def fib2(n,memo): 2 global numCalls 3 numCalls += 1 4 print "--->",n 5 if not n in memo: 6 memo[n] = fib2(n-1,memo)+fib2(n-2,memo) 7 return memo[n] 8 def fib1(n): 9 memo = {0:1,1:1} 10 return fib2(n,memo) 11 numCalls = 0 12 print fib1(6)
我们把执行结果都存到memo中,然后每次执行前都看下是不是在memo中。这样也是一种牺牲空间换取时间的做法,但是我们要知道,我们这样做避免了一次指数级的运算
这就是所谓的动态规则。它适用于,获得最优子机构的时候,局部解决方案有重叠的时候。