算法篇-动态规划算法

该篇属于算法初始篇,对于非专业人士,或者没有相关概念的人来说,或许对算法这个概念没有一个清晰形象的认识,因此首先说明什么是算法,怎么定义一个算法。

算法的定义和相关概念的介绍

算法是计算科学种用来描述一段指令对特定的输入通过算法程序后得到正确的结果,这个特定的程序又或者指令集就叫做算法,算法的目的是为了进行一定的运算并得到结果,算法解决的是数据问题,而解决问题的方式便是通过计算机的计算。算法通过计算机的计算解决实际问题,那么首先算法的本身执行的条件是有限制的,算法的问题必须是能够被量化的,能够让计算识别的,因此算法的输入必定是要符合一定条件的,在这个计算机本身的能力限制下,算法并不能解决所有的问题,而只能解决一些隐藏在实际问题中的数学问题,这便是算法的根本,算法实际上进行的就是数学运算,只是如何应用数学运算来得到结果,是所有算法工程师都需要努力的方向。

从上面可以看出,算法是用来解决实际问题的,这个问题必须能够被量化,具有一定的数学规律,同时他的结果也必然是数学的。举个栗子,如果我们要找出我们班级中第一名的成绩的分数,也就是在一组数字中找到最大值,在没有计算机的情况下,我们会首先在我们能够看到成绩范围内找出最大的数字,然后再接下来往下面找第二个区域找是否有比他最大的数字,如果有则把最大数字换成新出现的最大值,没有则继续往下找,知道所有人的成绩都被我们看完位置,我们得到了班级中成绩最大的人的最大值,这就是第一。对于计算机,要查找一组数中的最大值,也是同样的原理,只是计算机每次只能比较一个值,而不像人脑,能够一眼就看出一群数字中的最大值,可以说是相当低能了基础了,但正是基于这个低级的操作,才保证了他的结果永远不会出错,首先我们将成绩单一个一个的输入的计算机,计算机会用一种数据结果将其保存起来,最为普遍的就是用数组来保存每个成绩,这就是将实际问题转换为一个计算机可以识别的输入,也就是一串数字,所设计的算法便是要操作这个数组,最后返回一个最大值。根据前面的方式,我们通过先找到一个最大值,然后再跟后面的值比较,最后得到整个表的最大值,计算机也可以实现这样的思维逻辑,通过先取出数组中的第一个值作为最大值,然后循环的一个一个的往下面比较,直到遍历完整个数组。

算法中遍历是用的特别最多的情况,也是算法优化的主要方向。而针对每个算法的循环体,都会有这样一个衡量标准来验证算法的正确性,循环不变式是算法中所有循环都必须保证的条件,那前面提到的求最大值算法来说,我们应用了一个循环来进行数组的遍历,依此来找到数组的最大值,循环不变式便是描述每一次遍历,循环的结果始终都是当前所有已经遍历元素中最大的一个,也就是循环的结果对于当前已经遍历的结果是不变的,就好比如我们要遍历一个[0,2,1,2,5,3,2]的数组,当我们遍历到第一个元素的时候,所有已经遍历的结果是[0],这个数组中的最大值是0,第二次循环所有遍历的元素组成的数组是[0,2],当前最大值是2,第三次循环的时候,所有以遍历的元素组成的数组是[0,2,1],最大值是2,可以看出,对于一个正确的循环来说,无论什么时候跳出循环,结果都会是已经遍历的所有元素中组成的集合中我们想要的结果,也就是正确的答案,循环不变式是为了验证一个算法是否具有特殊情况,针对一个相同的类型的输入,只是输入规模的变化是否会引起算法本身结果发生变化。

从数学的角度讲,将输入定义为一个集合Q,将输出定义为一个集合R,那么R属于(Q,R)的一个子集,这有点抽象,有个课程是这么定义的,算法就是保证输入一个集合Q得到一个特定的集合R。

动态规划算法

好了,干货来了,之所以要写这篇文章,主要是为了加深对这个算法的理解。大概一周前就开始接触这个算法,但始终对实际问题没法进行很好的应用,只会套模板,这样实际上还是远远达不到能够解决实际问题的程度。

动态规划算法。首先他要解决的实际问题,就目前来看,动态规划算法适合解决一些再一堆特定条件下,寻找一种最优解决方案的算法,最先接触这个算法是在对加权有向图中寻找任意一对节点的权值和最小值,然后又在寻找字符串中最大子序列中遇见,最后又在字符串的最优转换问题中遇见,可以说,动态规划算法适合应用的一个特征就是寻找最优解的问题出现。

寻找最优解的算法实际上还有很多,比如贪心算法(不是很了解),而要使用动态规划算法,必然要符合一定的条件,动态规划算法是基于分治法思想下的一类算法,他是将问题分解为一连串的子问题,而通过解决子问题最后自底而上的解决整个问题,所以能否通过这个算法解决问题,我们首先要分析这个问题是否能够被递归为解决其子问题(贪心算法应用分治法的思想),并且这个子问题一定也是该子问题所涉及的数据规模中的最优解,也就是这个子问题的结果必然是被包含于总问题的,同时这个子问题和总问题只是在数据规模上有差距,而解决的问题本身是一致的(只有复合这个条件,我们才能通过迭代穷尽所有子问题,否则不满足循环不变式的规定),所以在应用算法之初,必须得确定算法是否符合动态规划算法得应用。

当确定了问题是能够通过动态规划算法解决后,接下来就是将问题量化为算法需要得输入了,首先,动态规划算法必然存在根据输入规模发生改变而结果也会发生改变的数组,也拿上面的求最大值的问题来做比,必然存在输入为i时存在一个最大值令这个值为c[i],同时必然存在当输入为i=0时,c[0]等于负无穷,令0<=i<=n(n为我们实际上要求范围),也就是将问题分解为求输入规模为i的最小值,并且一定满足当c[i]是输入0-i中的最大值时,那么其一定也是输入0-(i-1)中的最大值,如果最大值不等于数组a(输入数组)中最大值,那么一定会等于c[i-1]中的最大值。也就是如果max != a[i] 那么c[i-1],这里就是动态规划算法的关键,将这个问题的求解抛给他的子数组来解决,这里只是简单的应用,有些情况更复杂的需要通过同样的思维方式,首先预定一个关于输入规模的集合,然后对输入规模依次递减,寻找子问题的结果。

上面的求最大值算法应用动态规划后就成为:

1,令c[0]=-999999,a为包含所有成绩的数组包含n个元素

2,令i从1到n

    如果a[i]>c[i-1]则c[i]=a[i]

    否则c[i] = c[i-1]

可以看出,换了一种思维方式,我们同样能够解决最大值的求解,输入和结果没发生变化,只是解决问题的方式发生了变化,甚至仔细观察这个算法所执行的步骤,跟我们最开始普通的求最大值算法的思维逻辑是一致的,只是算法的本身思考的逻辑却是变得更加复杂了,而如果真的用这种算法来求最大值,那就真的是大材小用了,动态规划算法,更适合应用于一些更加复杂的问题上面,比如地图上面两点之间的最优行车路线的计算。

你可能感兴趣的:(算法篇-动态规划算法)