【零基础】学python数据结构与算法笔记14-动态规划


前言

学习python数据结构与算法,学习常用的算法,
b站学习链接

88.动态规划介绍

动态规划在基因测序、基因比对、hmm 有应用场景。

从斐波那契数列看动态规划
在这里插入图片描述
练习: 使用递归和非递归的方法来求解斐波那契数列。

在这里插入图片描述
这种非递归求斐波那契数,可以看成是一个动态规划思想,每次都会把重复子问题的答案存起来。

89.钢条切割问题

在这里插入图片描述
在这里插入图片描述
长度为n的一共有n-1口可以切,每一口可以选择切或者不切,所以有2^n-1种不同的方法。

在这里插入图片描述
r[i]那行是长度为i时,最多买的钱。可以这样考虑,在长度为2时,可以选择切成1和1 或者不切,不切最大利润是5,切了后最大利润是2,把最大利润存到r[2]下,当r[3]时,可以不切或者切成1和2(不考虑切成1、1、1,因为在r[2]中已经考虑过1和1 的利润没2大),选择最大的8存放在r[3]中,按照这样的思想,比方说看r[9],看不切或1和8或2和7或3和6或4和5,选择最大的放到r[9],
先看1和8,1+22
2和7,5+18
3和6,8+17
4和5,10+13
于是我们可以推出递推式,不切和切一刀之后最大值就是利润最大。此时从左边往右边切和从右边往左切是一样的,但我们还是考虑了切成5和4,切成6和3的情况。
在这里插入图片描述
我们可以将求解规模为n的原问题划分成规模更小的子问题:完成一次切割后,可以将产生的两端钢条看成两个独立的钢条切割问题,

在这里插入图片描述
这就叫最优子结构,把9的最大=3最大+6最大。

此时可以得出以上的递推式,不过还可以再进行简化,以上是不切和切一次的不同位置来构成的递推式。
在这里插入图片描述
这样还是切9, 左边一部分是不切的,所以价值是原来不切的价值
1和8,1+20
2和7,5+18
3和6,8+17
4和5,9+13
5和4,10+10
6和3,17+8
7和2,17+5
8和1,20+1
25还是最大,为什么可以这样做呢?因为现在最大是3和6 实则是3和6,但假设如果最大是23 那就是2和2和2和3,2没切,后面的7切成了三段,或者假设说是4和5,4没切,5切成2和3,那么就是说,这样左边没切,右边切,所有的情况还是都能列举,之前的方法有重复了,所以可以这样简化。

90.钢条切割问题:自顶向下实现

对照上面的公式写出以下两种实现,第二种简化的方法,少了一次递归,时间上少了很多。
在这里插入图片描述
将p改成p = [0,1,5,8,9,10,17,17,20,24,30,31,33,35,36,40,41,42,45,46,50],长度改大,计算最大的时间也变慢了。

在这里插入图片描述
因为递归算法由于重复求解相同子问题,效率极低,随着长度越大,求解速度会变慢
在这里插入图片描述
因为这是用了自顶向下递归实现,为何自顶向下递归的效率会这么差?
时间复杂度为O(2^n),如果n越大,就会造成指数爆炸。
求f(4),会重复求许多相同的问题。
在这里插入图片描述

动态规划的思想:每个问题只求解一次,保存求解结果
之后需要此问题时,只需要查找并保存结果。

91.钢条切割问题:自底向上实现

动态规划就是自底向上实现,每次都把最好的存起来,调用时直接取出来,不用再算。
按照第二种简化的方法写。
在这里插入图片描述
时间上比递归的方法快很多,时间复杂度为O(n^2)
在这里插入图片描述

92.钢条切割问题:重构解

如何修改动态规划算法,使其不仅输出最优解,还输出最优切割方案?
对每个问题,保存切割一次时左切切下的长度,s[i]为保存的当前最优利润时,左切下的长度
在这里插入图片描述
max()的话就不知道里面左边不切割的长度是多少,所以要换成以下写法
在这里插入图片描述
实际上这样把每次切出来的长度列出来,有个专有的名词叫路径带回
在这里插入图片描述
什么问题可以用动态规划方法?涉及到最大,最小,最优时
z
实际上,贪心算法是动态规划一个特例,贪心能解动态也能解,贪心不能解,动态也能解。
可以先从递归的思想想问题,如果递归能解就意味着动态规划能解。

93.最长公共子序列

在这里插入图片描述
首先要找到递推式或者说是最优子结构。
我们发现这样一个规律,如果两个字符串的最后一个字符不相等,比如说“ABCBDAB”和“BDCABA”这两个字符串找最长公共子序列。我们先看最后一个字符,不一样,那么我们可以等同于“ABCBDAB”和“BDCAB”中找最长公共子序列,或者“ABCBDA”和“BDCABA”中找,两者中哪个最长就是最长的公共子序列。如果最后一个字符一样,比如“ABCBDA”和“BDCABA”,那么最长的公共子序列就等于“ABCBD”和“BDCAB”的最长公共子序列 +1(因为最后一个字符相等)。
就得出如下定理:
在这里插入图片描述
安照这个图得出,空字符时都为0,如果末尾字符相等,那就取上面格子和下面格子的最大值,如果不相等,就取左上角一个格子的值+1。(从左上角过来的值代表匹配)
在这里插入图片描述

94.最长公共子序列:实现

首先求最长公共子序列的长度
在这里插入图片描述
再利用回溯法得出,这个最长的子序列的字符是多少
在这里插入图片描述
这种做法只能求得一个,如果 elif c[i-1][j] > c[i][j-1]: 改成 >= 则答案是BCBA,这两个都是最长公共子序列,所以都是对的。
存的路径如下。
在这里插入图片描述

总结

学习了动态规划算法。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值