动态规划——DP 核心:递推式
动态规划(DP)的思想: 最优子结构 = 调试;重复子问题
从斐波那契数列看动态规划: 斐波那契数列:Fn = Fn-1 + Fn-2 使用递归和非递归的方法来求解斐波那契数列的第n项 使用递归写法:
def fibnacci(n): if n==1 or n==2: return 1 else: return fibnacci(n-1) + fibnacci(n-2) print(fibnacci(100))
递归很慢!!!
使用非递归写法:
def fibnacii_no_recurision(n): f = [0,1,1] if n > 2: for i in range(n-2): num = f[-1] + f[-2] f.append(num) return f[n] print(fibnacii_no_recurision(100))
当n等于100时,可以看出非递归计算得很快,但是递归很慢,这就涉及到子问题的重复问题了
这里可以看出递归的时候,每个f(n) 都是独立的,所以一直重复计算一个一样的值,使得效率低下,
非递归的想法就是动态规划的思想
动态规划之钢条切割问题
假定我们知道某公司出售一段长度为i英寸的钢条的价格为p钢条长度为整英寸如图给出价格表的描述(任意长度的钢条价格都有) 现在先给一段长度为n的钢条,问怎么切割,获得的收益最大 rn? 考虑n=4的时候,有以下8种切割方式 假如一个最优解把n段切成了k段(1<=k<=n),那么最优切割方案: i及下标表示第i段的长度,n为钢条的总长度。
最大收益: p及下标表示第i段的收益,r为钢条的总收益
设长度为n的钢条切割后最优收益值为rn,可以得出递推式: rn = max(pn,r1+rn-1,r2+rn-2…) 第一个参数pn表示不切割 其他n-1个参数分别表示另外n-1种不同切割方案,对方案i=1,i=2… 将钢条切割为长度i和n-i两段 方案i的收益为切割两段的最优收益之和 小问题的最优解可以构造大问题的最优解的时候就称为最优子结构 钢条切割问题还存在更简单的递归求解方案 从钢条的左边切割下长度为i的一段,只对右边剩下的一段继续切割左边的不再切割 递推式简化为:rn = max(pi+rn-i) 这里的pi帮大家理解下:始终还要切 一直切到r1 递归代码如下
#这里是公式为:rn = max(pn,r1+rn-1,r2+rn-2........) def cut_rod_recurision(p,n): if n==0: return 0 else: res = p[n] for i in range(1,n): res = max(res,cut_rod_recurision(p,i)+cut_rod_recurision(p,n-i)) return res print(cut_rod_recurision(p,9))
#这里是公式为:rn = max(pi+rn-i) def cut_rod_recurision_2(p,n): if n==0: return 0 else: res = 0 for i in range(1,n+1):#切 res = max(res,p[i] + cut_rod_recurision_2(p,n-i)) return res print(cut_rod_recurision_2(p,9))
dp解法如下:
def cut_road_dp(p,n): r = [0] for i in range(1,n+1): res = 0 for j in range(1,i+1): res = max(res,p[j] + r[i-j]) r.append(res) return r[n] #用空间换时间
上一篇:
92天倒计时,蓝桥杯省赛备赛攻略来啦~
下一篇:
楼下小超市系统测试用例大全