史上最容易理解的暴力递归和动态规划~~

            

        史上最容易理解的暴力递归和动态规划~~



    介绍递归和动态规划


暴力递归:
1, 把问题转化为
规模缩小了的同类问题的子问题
2, 有明确的不需要继续进行递归的条件(base case)
3, 有当得到了子问题的结果之后的决策过程

4, 不记录每一个子问题的解(区别于动态规划2)


动态规划
1, 从暴力递归中来
2, 将每一个子问题的解记录下来, 避免重复计算
3, 把暴力递归的过程, 抽象成了状态表达

4, 并且存在化简状态表达, 使其更加简洁的可能


动态规划其实是由暴力递归演变而来的,每个动态规划的接法基本都能找到其动态规划的版本~

他们的关系如下:

暴力递归------》依赖关系(套路,即记忆关系)------》动态规划


下面以一道题为例子来向大家详细的介绍一下:


先理解一下题意:

给定一个数组和一个整数,可以随便选择arr数组里面的数字,看看累加起来能不能得到aim,可以得到就返回true,不可以返回false

eg :arr[] = { 3, 2, 9, 7 };  Aim = 21;返回true 3+2+9+7=21

        arr[] = { 3, 2, 9, 7 }; Aim = 13;返回false,无法组合得到13



思路分析:

先用暴力递归的方式来解决:


先看一下方法的参数,参数有arr[]和Aim是题目提供的,我们自己定义的有i和sum,这两个参数是什么意思呢?

他们的含义是,在一个数组中,从i下标开始,可以任意去i后面的数进行累加,累加的和为sum,看图:



如果你能想到这个图或者说看到这个图,你就已经成功了一半~~

可以发现,要判断这个数组中是否有满足要求的组合,只要看最后一行是否有相应的aim值就可以了。

所以,就有了下面的暴力递归:



暴力递归之后,就是动态规划了~

来来来,重点来了,从暴力递归转变到动态规划,跟题意是没有半毛钱关系的~

下面划重点了:

暴力递归------》依赖关系(套路,即记忆关系)------》动态规划

这里还差了个依赖关系:

啥都别说了,先画个图吧嘻嘻~

还是以上面那个例子为主:

arr[3] = {2,3,7};

aim = 10;

那么i的取值范围就是0~3了

sum的取值则是2+3+7=12即(0~12)

先看暴力破解法的basecase:


辣么,第三行sum等于Aim的值就为true,其他为false;

再看基本关系:


通过细细分析,可以得到下面的依赖关系图了~

图中的方框加×是(i,sum)的依赖,也就是说,要想得到(I,sum)的值,只要知道两个方框加×里面的值就可以推出来了( 不是我说的,是程序里面体现出来的)那么,因为第三列的值都知道了,那么其他列的值肯定也可以通过这一列的值推出来,那么我们所要求的(0,0)的值不就出来了吗?


这个依赖关系出来之后,那么动态规划的解也就出来了~~~(开心)


其实这个方法我也是思考了很久才领悟的~

希望对你们也能有所帮助~~不懂欢迎留言,懂得帮忙点个赞~~~

猜你喜欢

转载自blog.csdn.net/weixin_37766296/article/details/80113760