动态规划基础教程
- 格式:pdf
- 大小:795.39 KB
- 文档页数:43
动态规划方案学习速成攻略与实践案例一、前言大家好,今天我来给大家分享一份关于动态规划的学习攻略和实践案例。
动态规划是算法领域的一种重要技术,广泛应用于各种场景,如最长公共子序列、背包问题、最长递增子序列等。
掌握动态规划,不仅可以提高解决问题的效率,还可以提升自己的编程能力。
我们就一起走进动态规划的世界,探寻其中的奥秘。
二、动态规划学习攻略1.理解动态规划的基本概念动态规划是一种分阶段决策的过程,它将一个问题分解为若干个子问题,并通过解决子问题来求解原问题。
动态规划的核心思想是保存子问题的解,避免重复计算。
2.掌握动态规划的解题步骤(1)明确状态:将问题分解为若干个子问题,并定义状态变量,这些状态变量可以用来描述子问题的解。
(2)建立状态转移方程:根据子问题之间的关系,找出状态之间的转移规律,建立状态转移方程。
(3)确定边界条件:为了解决边界问题,需要为状态转移方程设定合适的边界条件。
(4)计算最优解:根据状态转移方程和边界条件,计算出问题的最优解。
3.学习动态规划的常用技巧(1)画出状态转移图:通过画出状态转移图,可以更清晰地理解状态之间的转移关系。
(2)使用表格法:将状态和状态转移方程写成表格形式,便于分析和计算。
(3)利用代码实现:通过编写代码,将动态规划的思想转化为程序,验证自己的思路。
三、动态规划实践案例1.最长公共子序列最长公共子序列(LongestCommonSubsequence,LCS)问题是动态规划的经典问题之一。
给定两个序列X和Y,求它们的最长公共子序列。
案例分析:我们可以用一个二维数组dp来表示X和Y的最长公共子序列。
dp[i][j]表示X的前i个字符与Y的前j个字符的最长公共子序列的长度。
状态转移方程为:dp[i][j]={dp[i-1][j-1]+1,ifX[i]==Y[j]max(dp[i-1][j],dp[i][j-1]),otherwise}代码实现:defLCS(X,Y):m,n=len(X),len(Y)dp=[[0](n+1)for_inrange(m+1)]foriinrange(1,m+1):forjinrange(1,n+1):ifX[i-1]==Y[j-1]:dp[i][j]=dp[i-1][j-1]+1else:dp[i][j]=max(dp[i-1][j],dp[i][j-1])returndp[m][n]2.0-1背包问题0-1背包问题是动态规划的另一个经典问题。
动态规划算法⼊门1. 动态规划算法定义:动态规划,英⽂描述为Dynamic programming. 是⼀种可以把原始问题分解为若⼲相关联的⼦解问题,并通过求取和保存⼦问题的解,获得原问题的解。
动态规划算法可以解决的问题通常包含如下特征:重叠⼦问题最优⼦结构 对于第⼀个特征,⽐较容易理解,即分解的若⼲⼦问题,包含着重复的解。
举例如:斐波那契数列,F(n) = F(n-1) + F(n-2),求解的F(n-1)的过程中,包含着求解F(n-2)的结果。
对于第⼆个特征,参考⽹上的说法为:假设当前决策结果是f[n],则最优⼦结构就是要让f[n-k]最优,最优⼦结构性质就是能让转移到n的状态是最优的,并且与后⾯的决策没有关系,即让后⾯的决策安⼼地使⽤前⾯的局部最优解的⼀种性质。
关键字解读为:当前的决策与后⾯的决策是⽆关的, f[n-k]是最优的,转移到f[n]的状态是最优的2. 动态规划算法的⼀般步骤和难点使⽤动态规划算法解决问题的⼀般步骤是:找到问题的最优解的性质,⽤数学公式或者算法描述拆解⼦问题,确定问题的递推结构,保证可以收敛。
⽤知乎⼤神们的总结就是:找到问题的状态描述和状态转移⽅程。
3. 动态规划算法的分类和理解根据我的理解,以及⽹上的说法,我把动态规划算法分为三个类别和层次:简单动态规划算法,即状态⽅程是⽤⼀个维度的变量的描述的,常见的问题如:斐波那契数列,爬台阶问题等 爬台阶问题问题描述:有⼀座⾼度是10级台阶的楼梯,从下往上⾛,每跨⼀步只能向上1级或者2级台阶。
要求⽤程序来求出⼀共有多少种⾛法。
状态描述:我们使⽤变量n表⽰台阶的级数,F(n)表⽰n级台阶⼀共有多少种⾛法 状态转移⽅程与问题分解:根据每次能跨越的台阶数⽬:1级台阶或者2级台阶,因为⾛到N级台阶之前,⼈⼀定是处于N-1级台阶或者N-2级台阶。
F(n)的⾛法,⼀定是n-1级别的台阶的所有的⾛法和n-2级别台阶的所有⾛法之和。
F(n) = F(n-1) + F(n-2); 关于状态的分解,更详细的说明,可以看这篇⽂章:。
[转载]教你彻底学会动态规划——⼊门篇动态规划相信⼤家都知道,动态规划算法也是新⼿在刚接触算法设计时很苦恼的问题,有时候觉得难以理解,但是真正理解之后,就会觉得动态规划其实并没有想象中那么难。
⽹上也有很多关于讲解动态规划的⽂章,⼤多都是叙述概念,讲解原理,让⼈觉得晦涩难懂,即使⼀时间看懂了,发现当⾃⼰做题的时候⼜会觉得⽆所适从。
我觉得,理解算法最重要的还是在于练习,只有通过⾃⼰练习,才可以更快地提升。
话不多说,接下来,下⾯我就通过⼀个例⼦来⼀步⼀步讲解动态规划是怎样使⽤的,只有知道怎样使⽤,才能更好地理解,⽽不是⼀味地对概念和原理进⾏反复琢磨。
⾸先,我们看⼀下这道题(此题⽬来源于北⼤POJ):数字三⾓形(POJ1163)在上⾯的数字三⾓形中寻找⼀条从顶部到底边的路径,使得路径上所经过的数字之和最⼤。
路径上的每⼀步都只能往左下或右下⾛。
只需要求出这个最⼤和即可,不必给出具体路径。
三⾓形的⾏数⼤于1⼩于等于100,数字为 0 - 99输⼊格式:5 //表⽰三⾓形的⾏数接下来输⼊三⾓形73 88 1 02 7 4 44 5 2 6 5要求输出最⼤和接下来,我们来分析⼀下解题思路:⾸先,肯定得⽤⼆维数组来存放数字三⾓形然后我们⽤D( r, j) 来表⽰第r⾏第 j 个数字(r,j从1开始算)我们⽤MaxSum(r, j)表⽰从D(r,j)到底边的各条路径中,最佳路径的数字之和。
因此,此题的最终问题就变成了求 MaxSum(1,1)当我们看到这个题⽬的时候,⾸先想到的就是可以⽤简单的递归来解题:D(r, j)出发,下⼀步只能⾛D(r+1,j)或者D(r+1, j+1)。
故对于N⾏的三⾓形,我们可以写出如下的递归式:if ( r == N)MaxSum(r,j) = D(r,j)elseMaxSum( r, j) = Max{ MaxSum(r+1,j), MaxSum(r+1,j+1) } + D(r,j)根据上⾯这个简单的递归式,我们就可以很轻松地写出完整的递归代码:#include <iostream>#include <algorithm>#define MAX 101using namespace std;int D[MAX][MAX];int n;int MaxSum(int i, int j){if(i==n)return D[i][j];int x = MaxSum(i+1,j);int y = MaxSum(i+1,j+1);return max(x,y)+D[i][j];}int main(){int i,j;cin >> n;for(i=1;i<=n;i++)for(j=1;j<=i;j++)cin >> D[i][j];cout << MaxSum(1,1) << endl;}对于如上这段递归的代码,当我提交到POJ时,会显⽰如下结果:对的,代码运⾏超时了,为什么会超时呢?答案很简单,因为我们重复计算了,当我们在进⾏递归时,计算机帮我们计算的过程如下图:就拿第三⾏数字1来说,当我们计算从第2⾏的数字3开始的MaxSum时会计算出从1开始的MaxSum,当我们计算从第⼆⾏的数字8开始的MaxSum的时候⼜会计算⼀次从1开始的MaxSum,也就是说有重复计算。
动态规划经典教程第一节动态规划基本概念一,动态规划三要素:阶段,状态,决策。
他们的概念到处都是,我就不多说了,我只说说我对他们的理解:如果把动态规划的求解过程看成一个工厂的生产线,阶段就是生产某个商品的不同的环节,状态就是工件当前的形态,决策就是对工件的操作。
显然不同阶段是对产品的一个前面各个状态的小结,有一个个的小结构成了最终的整个生产线。
每个状态间又有关联(下一个状态是由上一个状态做了某个决策后产生的)。
下面举个例子:要生产一批雪糕,在这个过程中要分好多环节:购买牛奶,对牛奶提纯处理,放入工厂加工,加工后的商品要包装,包装后就去销售……,这样没个环节就可以看做是一个阶段;产品在不同的时候有不同的状态,刚开始时只是白白的牛奶,进入生产后做成了各种造型,从冷冻库拿出来后就变成雪糕(由液态变成固态=_=||)。
每个形态就是一个状态,那从液态变成固态经过了冰冻这一操作,这个操作就是一个决策。
一个状态经过一个决策变成了另外一个状态,这个过程就是状态转移,用来描述状态转移的方程就是状态转移方程。
经过这个例子相信大家对动态规划有所了解了吧。
下面在说说我对动态规划的另外一个理解:用图论知识理解动态规划:把动态规划中的状态抽象成一个点,在有直接关联的状态间连一条有向边,状态转移的代价就是边上的权。
这样就形成了一个有向无环图AOE网(为什么无环呢?往下看)。
对这个图进行拓扑排序,删除一个边后同时出现入度为0的状态在同一阶段。
这样对图求最优路径就是动态规划问题的求解。
二,动态规划的适用范围动态规划用于解决多阶段决策最优化问题,但是不是所有的最优化问题都可以用动态规划解答呢?一般在题目中出现求最优解的问题就要考虑动态规划了,但是否可以用还要满足两个条件:最优子结构(最优化原理)无后效性最优化原理在下面的最短路径问题中有详细的解答;什么是无后效性呢?就是说在状态i求解时用到状态j而状态j就解有用到状态k…..状态N。