算法-3B

算法-3B

这章的重点在于动态规划。而动态规划和分而治之的很大区别就在于,分而治之我们是不想分出来的子问题有联系的,但如果实在子问题之间具有联系,我们一般用动态规划来解决。当然动态规划也不是万能的。动态规划的两个好处1,可以解决很多实际问题,所以学起来会很有成就感。2,动态规划的模板是有套路的,所以在竞赛中出现的比例远远高于它实际在算法中占的比例。

遇见了同期算法训练营的师兄弟
这部分可参考https://blog.csdn.net/weixin_43829465/article/details/97810853

动态规划-1

在这里插入图片描述
谈到动态规划,就不得不谈到斐波拉比数列,因为当我们不使用记忆化(存储中间每一个结果)时,它的复杂度是指数增长,也就是我们常说会爆炸的。邓老师做了一个演示,大概在计算到四十几时,我们的每个结果的计算将慢到肉眼可见,再往后甚至慢的让人烦躁。如图所示斐波拉比数列的计算是第i项为i-1项和i-2项的和。
在这里插入图片描述

int fib(n){ return (2>n) ? n : fib(n-1)+fin(n-2) ; }

这样的递归会造成大量的重复,邓老师甚至给出了复杂度,是指数的,1.618的n次方,而计算机一秒大概算10的9次方,也就是2的30次方,也就是1.618的43次方左右,这也说明了为什么我们算到四十几项时,后一项的计算将慢到肉眼可见。
在这里插入图片描述
但如果对斐波拉比数列进行记忆化,记录它的每一个从底往上计算出来的值,那我们的效率将大大提高,时间复杂度大大降低,这就是我们动态规划的思想。
在这里插入图片描述
如图所示,对于计算第六项,我们灰色的部分就是我们免去的重复操作,如果这个项数再大一些,我们省去的重复操作将是一个惊人的部分。
在这里插入图片描述
幂法也是动态规划的经典题。如果要求一个数的很大次幂,光一项一项去乘,那是很慢效率很低的,我们可以先得到a的1次方,通过这个再得到a的10次方,再通过a的10次方得到a的100次方,以此类推,就不用再做很多重复操作了。
在这里插入图片描述
计算a^ n 所需要复杂度不用幂法的话是O(n), 用幂法(动态规划)的话则是DP O(r), r=logn为分解形成的位数。

动态规划-2

在这里插入图片描述
第二小节课,我们讲到了最短向上路径问题,如图所示,我们需要找到到达顶端而所耗路程(权重)最小的路。
在这里插入图片描述
如果从上往下分析,每个k层的点,可以由三个k-1层的点来到达,那么到底由哪个到达呢?我们并不知道,需要做判断,那么再往下分析(递归)每个k-1层的点又可以由3个k-2层的点到达,那么这种递增是指数的,3的n次方,指数无疑是可怕的,k-2到k-1层再到k层的路径里,存在着大量的重复,如图下方左边,这样是不可取的。
在这里插入图片描述
那么如果运用动态规划会怎样呢?我们来看看图下方的右边,不过我一般喜欢递推的话是以k层为中心,也就是图下方的左边,把箭头倒过来罢了,这样理解完全没有问题,只是把谁看作中心罢了,邓老师的右边是把k-1看作中心。动态规划的话,从底向上,我们的k层只要考虑可以经过它的三个点,哪个最小就可以,而最小是很容易在递推的过程中得到的,因为我们的最底层是知道的,这样从最底层确定倒数第二层,再依次往上,这样的作法明确了每一步的操作(与上面的并不知道相对应),不会产生大量的重复,可谓神奇。
在这里插入图片描述
再来一个问题就是曼哈顿街区了,我们从左上角出发,要到达右下角,路上每个节点有对应权重的红包,怎样才能使我们最终拿到的红包最大呢?因为不能因为红包而绕路,所以我们每一步只能向右或向下走。
在这里插入图片描述
看到这里聪明的同学会发现,这和我们的上一个最短向上路径特别相像。只不过这里的每一个节点只能从左节点或者上节点到达。如果我们从最高层右下角向左上方分析,我们会一样每一步不确定来自哪个节点,而产生大量的重复。如果使用动态规划就从底层开始明确了每一步的操作。(如果想更好的理解DP,可以看左边的图,但把箭头倒过来)

动态规划-3

在这里插入图片描述
第三节则讲到了最长公共子序列。在两个字符串中,找到他们的最长公共子序列,当然有可能最长公共子序列并不是唯一的。
在这里插入图片描述
那我们从末端开始分析,有两种情况,一种是末尾元素相等,如果相等的话则切掉末尾部分,因为已经相等了,记录下来就好,并不会影响两个前面的新串的比较。这里是减而治之的思想。
在这里插入图片描述
如果不同的话,则我们要用到分而治之的思想了。不同的话我们做两个操作,要么把第一个字符串往后移然后再做新比较。或者把第二个字符串往后移再做新的比较。这里面临两种情况的选择。
在这里插入图片描述
如图所示,每一步可以有三个去向。但这样的形式无疑会和我们之前的一样,会产生大量的重复。(动态规划,我们主要以已知推位置,由确定的推不确定的,因为确定的会选择其中的某一个,就会断掉其它路线,而避免产生重复,这里的起始端已经有我们确定的了,所以往后走的每一步它会考虑最好的而断掉其它路线,如下图)
在这里插入图片描述
第一行第一列人为已经给定了,全是0。
在这里插入图片描述
像这样从起始端开始递推,每一步我们会选择三个确定来源里面的最好的来源。
在这里插入图片描述
再来看01背包问题,也是动态规划里面的老经典了。我们有vi和wi,要使vi的和最大而wi的和小于给定的W。这就是著名的背包问题。
在这里插入图片描述
这是背包问题的演示图。
在这里插入图片描述
与上面讲到的其它类型题目不一样的一点是,我们的节点现在有两个来源,一个是上方,还有一个是左上方但横坐标不定,是W-wi,具体值由wi决定左上方多少。
在这里插入图片描述
哪怕我们用了动态规划,从起始到末尾,从底层到高层,从确定到不确定,但是由于我们的w可能是小数,又可能是一个很大的值,所以我们的算法还是可能会出现爆炸,主要是因为w可能是小数。
在这里插入图片描述
再来看一个传递闭包的问题。我们已知哪个点可以直接到达哪个点,但我们想知道哪个点还可以间接的到达哪个点,也就是图中红色线的部分。但其实算法很简单,如右图,只要k能到v点,而u能到k点,所以u一定能到v点,所以本来就是绿色的两个点和我们的(k,k)点确定的矩形,那第四个点就是我们新的红点,我们也可以标为1。
在这里插入图片描述
如图所示,增加红点。
在这里插入图片描述
两个已有的绿点,确定新的红点。
在这里插入图片描述
每次传递,都要通过(k,k)点和两个绿点确定的矩形,剩下的第四个点就是我们新的红点,我们的传递必须通过对角线传递。
在这里插入图片描述
这是我们的代码,三层循环就可以决定。45行和67行是一样的作用,不过67行更取巧,在64位的机器上可以快速跑出,不过不用也无伤大雅。
在这里插入图片描述
而看到这个,不知道大家有没有想起我们之前学过的最短路径,我们的这个算法也可以解决我们的最短路径问题。如图,我们两条线,可以确定一条新的线,但比上面的确定新的可到达点,这次不仅仅表示可到达,还可以表示到达的权重是多少,在我们传递的过程中,权值还会不断的改变,如果发现一条新的道路可以更短的到达,那么就更新那个点,表示那个点的横纵坐标两个点之间新的更短路径。
在这里插入图片描述
这是演示图,我们知道新的两点之间可以间接到达。
在这里插入图片描述
同样也只能是沿(k,k)对角线传递,更新完后,我们可以轻易找出两个点之间的最短路径,不过图中是有向图,两点之间方向不一样可能路径数值不一样。

结尾

这两天高产像母猪,我淦!不过开心(✪▽✪)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值