动态规划阶段总结之基础篇[必看]
动态规划超级详细的讲义

动态规划入门1(2008-09-20 21:40:51)第一节动态规划基本概念一,动态规划三要素:阶段,状态,决策。
他们的概念到处都是,我就不多说了,我只说说我对他们的理解:如果把动态规划的求解过程看成一个工厂的生产线,阶段就是生产某个商品的不同的环节,状态就是工件当前的形态,决策就是对工件的操作。
显然不同阶段是对产品的一个前面各个状态的小结,有一个个的小结构成了最终的整个生产线。
每个状态间又有关联(下一个状态是由上一个状态做了某个决策后产生的)。
下面举个例子:要生产一批雪糕,在这个过程中要分好多环节:购买牛奶,对牛奶提纯处理,放入工厂加工,加工后的商品要包装,包装后就去销售……,这样没个环节就可以看做是一个阶段;产品在不同的时候有不同的状态,刚开始时只是白白的牛奶,进入生产后做成了各种造型,从冷冻库拿出来后就变成雪糕(由液态变成固态=_=||)。
每个形态就是一个状态,那从液态变成固态经过了冰冻这一操作,这个操作就是一个决策。
一个状态经过一个决策变成了另外一个状态,这个过程就是状态转移,用来描述状态转移的方程就是状态转移方程。
经过这个例子相信大家对动态规划有所了解了吧。
下面在说说我对动态规划的另外一个理解:用图论知识理解动态规划:把动态规划中的状态抽象成一个点,在有直接关联的状态间连一条有向边,状态转移的代价就是边上的权。
这样就形成了一个有向无环图AOE网(为什么无环呢?往下看)。
对这个图进行拓扑排序,删除一个边后同时出现入度为0的状态在同一阶段。
这样对图求最优路径就是动态规划问题的求解。
二,动态规划的适用范围动态规划用于解决多阶段决策最优化问题,但是不是所有的最优化问题都可以用动态规划解答呢?一般在题目中出现求最优解的问题就要考虑动态规划了,但是否可以用还要满足两个条件:最优子结构(最优化原理)无后效性最优化原理在下面的最短路径问题中有详细的解答;什么是无后效性呢?就是说在状态i求解时用到状态j而状态j就解有用到状态k…..状态N。
动态规划的基本概念与方法

动态规划的基本概念与方法动态规划(Dynamic Programming,简称DP)是解决一类最优化问题的一种方法,也是算法设计中的重要思想。
动态规划常用于具有重叠子问题和最优子结构性质的问题。
它将问题分解为子问题,并通过求解子问题的最优解来得到原问题的最优解。
动态规划的基本概念是“最优子结构”。
也就是说,一个问题的最优解可以由其子问题的最优解推导出来。
通过分解问题为若干个子问题,可以形成一个递归的求解过程。
为了避免重复计算,动态规划使用一个表格来保存已经计算过的子问题的解,以便后续直接利用。
这个表格也被称为“记忆化表”或“DP表”。
动态规划的基本方法是“状态转移”。
状态转移指的是,通过已求解的子问题的解推导出更大规模子问题的解。
常用的状态转移方程可以通过问题的递推关系定义。
通过定义好状态转移方程,可以通过迭代的方式一步步求解问题的最优解。
在动态规划中,通常需要三个步骤来解决问题。
第一步,定义子问题。
将原问题划分为若干个子问题。
这些子问题通常与原问题具有相同的结构,只是规模更小。
例如,对于计算斐波那契数列的问题,可以定义子问题为计算第n个斐波那契数。
第二步,确定状态。
状态是求解问题所需要的所有变量的集合。
子问题的解需要用到的变量就是状态。
也就是说,状态是问题(解决方案)所需要的信息。
第三步,确定状态转移方程。
状态转移方程通过已求解的子问题的解推导出更大规模子问题的解。
通常情况下,状态转移方程可以通过问题的递推关系确定。
在实际应用中,动态规划常用于求解最优化问题。
最优化问题可以归纳为两类:一类是最大化问题,另一类是最小化问题。
例如,最长递增子序列问题是一个典型的最大化问题,而背包问题是一个典型的最小化问题。
动态规划的优势在于可以解决许多复杂问题,并且具有可行的计算复杂度。
但是,动态规划也有一些限制。
首先,动态规划要求问题具有重叠子问题和最优子结构性质,不是所有问题都能够满足这两个条件。
其次,动态规划需要存储计算过的子问题的解,对于一些问题来说,存储空间可能会非常大。
动态规划总结

动态规划总结动态规划系列内容算是结束了,虽然有关动态规划的知识点还有很多,但是我相信如果深刻掌握并理解了之前我们讲的内容,基本上leetcode 上面90% 以上的动态规划相关问题都可以很好解决。
动态规划就是利用历史记录,来避免我们的重复计算。
而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者二维数组来保存。
下面我们先来讲下做动态规划题很重要的三个步骤,第一步骤:定义数组元素的含义,上面说了,我们会用一个数组,来保存历史数组,假设用一维数组dp[] 吧。
这个时候有一个非常非常重要的点,就是规定你这个数组元素的含义,例如你的dp[i] 是代表什么意思?第二步骤:找出数组元素之间的关系式,我觉得动态规划,还是有一点类似于我们高中学习时的归纳法的,当我们要计算dp[n] 时,是可以利用dp[n-1],dp[n-2]…..dp[1],来推出dp[n] 的,也就是可以利用历史数据来推出新的元素值,所以我们要找出数组元素之间的关系式,例如dp[n] = dp[n-1] + dp[n-2],这个就是他们的关系式了。
而这一步,也是最难的一步,后面我会讲几种类型的题来说。
第三步骤:找出初始值。
学过数学归纳法的都知道,虽然我们知道了数组元素之间的关系式,例如dp[n] = dp[n-1] + dp[n-2],我们可以通过dp[n-1] 和dp[n-2] 来计算dp[n],但是,我们得知道初始值啊,例如一直推下去的话,会由dp[3] = dp[2] + dp[1]。
而dp[2] 和dp[1] 是不能再分解的了,所以我们必须要能够直接获得dp[2] 和dp[1] 的值,而这,就是所谓的初始值。
由了初始值,并且有了数组元素之间的关系式,那么我们就可以得到dp[n] 的值了,而dp[n] 的含义是由你来定义的,你想求什么,就定义它是什么,这样,这道题也就解出来了。
当然了,要想达到熟能生巧的程度,还是需要多加练习,多思考,多对比,多总结,不然的话,学到的东西很快就会忘记。
动态规划总结经典题目(经典中的经典)

动态规划总结——经典问题总结本文着重讨论状态是如何表示,以及方程是怎样表示的。
当然,还附上关键的,有可能作为模板的代码段。
但有的代码的实现是优化版的。
经典问题总结最长上升子序列(LIS)问题描述如下:设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。
求最大的m值。
这里采用的是逆向思维的方法,从最后一个开始想起,即先从A[N](A数组是存放数据的数组,下同)开始,则只有长度为1的子序列,到A[N-1]时就有两种情况,如果a[n-1] < a[n] 则存在长度为2的不下降子序列a[n-1],a[n];如果a[n-1] > a[n] 则存在长度为1的不下降子序列a[n-1]或者a[n]。
有了以上的思想,DP方程就呼之欲出了(这里是顺序推的,不是逆序的):DP[I]=MAX(1,DP[J]+1)J=0,1,...,I-1但这样的想法实现起来是)O(n^2)的。
本题还有更好的解法,就是O(n*logn)。
利用了长升子序列的性质来优化,以下是优化版的代码://最长不降子序const int SIZE=500001;int data[SIZE];int dp[SIZE];//返回值是最长不降子序列的最大长度,复杂度O(N*logN)int LCS(int n) { //N是DATA数组的长度,下标从1开始int len(1),low,high,mid,i;dp[1]=data[1];for(i=1;i<=n;++i) {low=1;high=len;while( low<=high ) { //二分mid=(low+high)/2;if( data[i]>dp[mid] ) {low=mid+1;}else {high=mid-1;}}dp[low]=data[i];if( low>len ) {++len;}}return len;}最长公共子序列(LCS)给出两个字符串a, b,求它们的最长、连续的公共字串。
动态规划总结汇总(NOIP必备)

动态规划(一)05B 张婕目录一、数字添加号 (2)二、乘积最大 (9)三、矩阵取数 (16)四、邮局(已修改) (22)五、棋盘分割 (28)六、矩阵连乘 (35)七、能量项链 (40)八、石子合并 (45)九、加分二叉树 (51)十、CUTTING(已修改) (56)1、数字添加号『题目描述』一个由数字1,2,... ,9组成的数字串(长度不超过200),问如何将M(M<=20)个加号("+")插入到这个数字串中,使所形成的算术表达式的值最小。
请编一个程序解决这个问题。
注意:加号不能加在数字串的最前面或最末尾,也不应有两个或两个以上的加号相邻。
M保证小于数字串的长度。
例如:数字串79846,若需要加入两个加号,则最佳方案为79+8+46,算术表达式的值133。
[输入格式]从键盘读入输入文件名。
数字串在输入文件的第一行行首(数字串中间无空格且不折行),M的值在输入文件的第二行行首。
[输出格式]在屏幕上输出所求得的最小和的精确值。
[输入输出举例]EXAM4.SAM823639837423EXAM4.SAM 2170『题意分析』1)任务:求在长度为n的数中添加m 个加号的最小值2)程序名 exam4.pas3)输入i.文件名 exam4.inii.格式及内容第一行数字串 n<=200(数字串中间无空格且不折行)第二行整数M m <= 20(所要添加的加号个数)4)输出i.文件名 exam4.outii.格式及内容所求得的最小和的精确值5)数据范围N <= 200, m <= 20注:□加号不能加在数字串的最前面或最末尾,也不应有两个或两个以上的加号相邻。
M保证小于数字串的长度。
『算法分析』1)根据样例模拟求解过程。
119191 2⎪⎪⎩⎪⎪⎨⎧=+=+=+=+=1391)1,5(19391)1,4(211191)1,3(91939191)1,2(139)2,6(f f f f f ⎪⎪⎩⎪⎪⎨⎧=+=+=+=+=12009)0,4(13819)0,3(930919)0,2(1901919)0,1(138)1,5(f f f f f ⎩⎨⎧=+=+==+=209)0,2(2019)0,1(20)1,3(21)0,1()1,2(f f f f f ⎪⎩⎪⎨⎧=+=+=+=1201)0,3(10291)0,2(192191)0,1(102)1,4(f f f f 2) 根据数据范围估算程序复杂度。
[转载]教你彻底学会动态规划——入门篇
![[转载]教你彻底学会动态规划——入门篇](https://img.taocdn.com/s3/m/cbb4df1ff02d2af90242a8956bec0975f465a40d.png)
[转载]教你彻底学会动态规划——⼊门篇动态规划相信⼤家都知道,动态规划算法也是新⼿在刚接触算法设计时很苦恼的问题,有时候觉得难以理解,但是真正理解之后,就会觉得动态规划其实并没有想象中那么难。
⽹上也有很多关于讲解动态规划的⽂章,⼤多都是叙述概念,讲解原理,让⼈觉得晦涩难懂,即使⼀时间看懂了,发现当⾃⼰做题的时候⼜会觉得⽆所适从。
我觉得,理解算法最重要的还是在于练习,只有通过⾃⼰练习,才可以更快地提升。
话不多说,接下来,下⾯我就通过⼀个例⼦来⼀步⼀步讲解动态规划是怎样使⽤的,只有知道怎样使⽤,才能更好地理解,⽽不是⼀味地对概念和原理进⾏反复琢磨。
⾸先,我们看⼀下这道题(此题⽬来源于北⼤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,也就是说有重复计算。
动态规划地地总结

动态规划总结by Amber1. 按状态类型分写在前面:从状态类型分,并不表示一题只从属于一类。
其实一类只是一种状态的表示方法。
可以好几种方法组合成一个状态,来解决问题。
1.1. 编号(长度)动态规划共性总结本类的状态是基础的基础,大部分的动态规划都要用到它,成为一个维。
一般来说,有两种编号的状态:状态(i)表示前i个元素决策组成的一个状态。
状态(i)表示用到了第i个元素,和其他在1到i-1问的元素,决策组成有的一个状态。
题库a) 最长不下降子序歹0以一元组(i)作为状态,表示第i个作为序列的最后一个点的时候的最长序列。
丁是很容易想到O(n2)得算法。
但本题可合理组织状态,引入一个单调的辅助数组,利用单调性二分查找,优化到O(nlogn)。
关丁优化详见优化章。
一些问题可将数据有序化,转化成本题。
应用:拦截导弹(NOIP99 Advance 1) 就是原题。
Beautiful People (sgu199),要将数据有序化:其中一个权作为第一关键字不下降排列,另一个权作为第二关键字不上升。
Segment(ural 1078),将线段的左端点有序化就可以了。
b) LCS状态(i,j),表示第1个字符申的第i位,与第2个字符申的第j位匹配,得到的最长的申。
若有多个申要LC§则加维,即几个申就几个维。
我也将此题归入路径问题。
c) 花店橱窗布置(IOI99)见路径问题。
1.2.区间动态规划共性总结本类问题与下一章的划分问题的决策的分割点无序交集比较大(占本类问题的30%。
题库a) 石子合并一见划分问题b) 模版匹配(CEOI01,Patten)这题特殊的地方是状态的值是一个集合而不是一个数。
c) 不可分解的编码(ACM World Final 2002)d) Electric Path (ural1143)e) 邮局(IOI2000 Day2 1)若状态表示的思路从第i个村庄可以从届丁哪个邮局,无最优子结构。
动态规划基础-----01背包(总结)

动态规划基础-----01背包(总结)1、动态规划(DP) 动态规划(Dynamic Programming,DP)与分治区别在于划分的⼦问题是有重叠的,解过程中对于重叠的部分只要求解⼀次,记录下结果,其他⼦问题直接使⽤即可,减少了重复计算过程。
另外,DP在求解⼀个问题最优解的时候,不是固定的计算合并某些⼦问题的解,⽽是根据各⼦问题的解的情况选择其中最优的。
动态规划求解具有以下的性质: 最优⼦结构性质、⼦问题重叠性质 最优⼦结构性质:最优解包含了其⼦问题的最优解,不是合并所有⼦问题的解,⽽是找最优的⼀条解线路,选择部分⼦最优解来达到最终的最优解。
⼦问题重叠性质:先计算⼦问题的解,再由⼦问题的解去构造问题的解(由于⼦问题存在重叠,把⼦问题解记录下来为下⼀步使⽤,这样就直接可以从备忘录中读取)。
其中备忘录中先记录初始状态。
2、求解思路 ①、将原问题分解为⼦问题(⼦问题和原问题形式相同,且⼦问题解求出就会被保存); ②、确定状态:01背包中⼀个状态就是个物体中第个是否放⼊体积为背包中; ③、确定⼀些初始状态(边界状态)的值; ④、确定状态转移⽅程,如何从⼀个或多个已知状态求出另⼀个未知状态的值。
(递推型)3、01背包问题求解思路 ①、确认⼦问题和状态 01背包问题需要求解的就是,为了体积V的背包中物体总价值最⼤化,件物品中第件应该放⼊背包中吗?(其中每个物品最多只能放⼀件) 为此,我们定义⼀个⼆维数组,其中每个元素代表⼀个状态,即前个物体中若⼲个放⼊体积为背包中最⼤价值。
数组为:,其中表⽰前件中若⼲个物品放⼊体积为的背包中的最⼤价值。
②、初始状态 初始状态为和都为0,前者表⽰前0个物品(也就是空物品)⽆论装⼊多⼤的包中总价值都为0,后者表⽰体积为0的背包啥价值的物品都装不进去。
我⾃⼰写的的没保存,只能把这个整来凑数了伪代码for(int t=1;t<=n;t++){for(int j=V;j>=v[t];j--){dp[j]=max(dp[j],dp[j-v[t]]+w[t]);}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划阶段总结之基础篇by Zc[序言]动态规划是信息学竞赛中最重要的知识点之一,不仅思维难度高,而且变化多端,新思想新方法层出不穷,要求选手具有很强的创新思维和细腻的思考。
这里基础篇从几个例题出发,向大家介绍几个动态规划中几种常见常用的模型,并简单介绍几种优化方法。
[正文]【模型一】例题:数字三角形73 88 1 02 7 4 44 5 2 6 5(图1)图1给出了一个数字三角形。
从三角形的顶部到底部有很多条不同的路径。
对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
注意:路径上的每一步只能从一个数走到下一层上和它最近的左边的那个数或者右边的那个数。
分析:这类问题一般比较简单,状态、阶段几乎是显而易见的,不过这也是动态规划中最基础最重要的几个概念,通过这样的例题,我们渐渐的能够认识到动态规划的本质。
状态:[,]F i j表示从顶部走到第i行第j个数字时最大的和是多少。
方程:[,]([1,1],[1,])[,]=---+F i j Max F i j F i j Num i j类似的例题还有NOIp2002普及组的过河卒、ZOJ 2271 Chance to Encounter a Girl、【模型二】例题:最长前缀一些生物体的复杂结构可以用其基元的序列表示,而一个基元用一个大写英文字符串表示。
生物学家的一个问题就是将一个这样的长序列分解为基元(字符串)的序列,对于给定的基元的集合P,如果可以从中选出N个基元P1,P2,…Pn,将它们各自对应的字符串依次联接后得到一个字符串S,称S可以由基元集合P构成。
在从P中挑选基元时,一个基元可以使用多次,也可以不用,例如,序列ABABACABAB可以由基元集合{A,AB,BA,CA,BBC}构成。
字符串的前K个字符称为该字符串的前缀,其长度为K.请写一个程序,对于输入的基元集合P和字符串T,求出一个可以由基元集合P构成的字符串T 的前缀,要求该前缀的长度尽可能的长,输出其长度。
分析:这是一类非常基础的线性模型,一般都是一维的状态,其基本的方程形式为[]([](,))F i Optimum F j W i j=+,W(i,j)为转移函数。
状态:[]F i表示长度为i的前缀最少由几个基元构成。
方程:[]([])1F i Min F j=+ | 条件为S[j+1..i] 为一个基元更复杂一点的就是二维的串模型,例如经典的LCS问题(最长公共序列)。
其状态为[,]F i j表示A串的前i个字符和B串的前j个字符的LCS的长度为多少。
方程:[1,1]1[][] [,]([,1],[1,][][]F i j A i B j F i jMax F i j F i j A i B j--+ | =⎧=⎨-- | ≠ ⎩虽然方程变成了2维,但是其本质还是线性的模型,其方程形式可以描述为[,]([,]( 1.., 1..))F i j Optimum F a b W a i b j=+++其经典例题有:LIS(最长不下降子序列)、ZOJ 2432 Greatest Common Increasing Subsequence、ZOJ 1792 Gap Punishment Aligment Problem、SGU 214 Weird Dissimilarity【模型三】例题:石子归并在一个圆形操场的四周摆放着N堆石子(N<= 100),现要将石子有次序地合并成一堆.规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.编一程序,由文件读入堆栈数N及每堆栈的石子数(<=20).(!)选择一种合并石子的方案,使用权得做N-1次合并,得分的总和最小;(2)选择一种合并石子的方案,使用权得做N-1次合并,得分的总和最大;分析:这类问题是基础动态规划中较为复杂的一种,不过其方程更加突出了动态规划递归子问题的特点。
状态:[,]F i j表示合并第i个到第j个石子的最小代价是多少,G i j表示合并第i个到第j个石子的最大代价是多少。
[,]方程:[,]([,][,])(,)=++F i j Min F i k F k j Merge i j[,]([,][,])(,)=++G i j Min G i k G k j Merge i j这个方程中体现的化归的思想非常重要,将当前大堆分成两小堆进行解决,以后的很多动态规划问题大多都是基于这种思想。
其经典例题有:IOI98 Polygon、POI99 Mustter、ZOJ 1554 Folding、UVA 10003 Cutting Stick、SGU 273 Game Po【模型四】例题:01背包问题1设n个重量为(W1,W2,...Wn)的物品和一个载重为S的背包,每个物品只能选择放或不放,将物品放进背包中的利润是Pi,问如何选择物品的种类和数量,使得背包获得最大的利润?分析:其实背包问题在理论上是NP问题的,当其背包的权值没有限制时是无法1我个人在感觉上觉得01背包这个模型其实和线性模型是非常相似的,但作为一个经典的模型,我还是把他独立出来了解决的,只有当权值较小时,才可以使用动态规划解决。
状态 :[,]F i j 表示放入前i 个物品且总重量不超过j 时能获得的最大利润 方程 : [,]([1,],[1,[]][])F i j Max F i j F i j w i p i =---+其经典例题有:ZOJ 1743 Concert Hall Scheduling 、原创试题《吃夜宵》【模型五】例题:数的拆分给定一个整数N ,现在要把n 分解成若干个整数的和,且分解出的整数不可重复,求总共的分解方案。
分析:统计问题一直是动态规划问题的重要分支之一,而动态规划虽然高效,但当问题规模变得很大时,仍需要我们进行优化才能使动态规划发挥其应有的用处。
这里结合这个问题提出一种非常简单的处理统计或最优问题的油画方法。
状态 : [,]F i j 表示将i 分解且分解出的最大数字不超过j 时分解的方案是多少。
方程 :1[,][,1]jk F i j F i k k ==--∑这个方程是O(N^3)的,但是它还是有非常大的优化空间的。
注意到 [,][1,0][2,1]...[1,2][,1][,1][1,0][2,1]...[1,2]F i j F i F i F i j j F i j j F i j F i F i F i j j =-+-++-+-+--⎧⎨-=-+-+-+-⎩两式相减得到[,][,1][,1]F i j F i j F i j j --=--综合得到优化后的方程为 [,][,1][,1]F i j F i j F i j j =-+--经典例题 :ZOJ 1234 Chopsticks 、ZOJ 1524 Supermarket 、ZOJ 2069 Greatest Least Common Multiple 、ZOJ 2230 Fourier's Lines这里我们将决策集合列出,并和以前得到的结果进行比较寻找相似的集合并直接引用以前的结果,达到优化决策的目的。
这里很幸运的,我们发现原状态数组中就是保存的决策集合,但是有的时候并没有这么巧的是,不过我们可以重新定义一个优化数组来保存决策的集合,并每次求出某个状态后用常数的时间来维护这个数组,以便达到优化常数甚至O(1)的决策。
[小结]本文简单的介绍了动态规划中最基本也是最常用的6个模型,细心的读者已经注意到,本文介绍的动态规划中只粗略的列出了动态规划时状态的设置以及大致方程,至于状态的边界及转移方法并无涉及,本文并无意指导大家学习写动态规划的程序,而是通过这几个经典的例子,向大家展示动态规划的一些基本思路及建模方向,如果仅仅只是拘泥于几个方程,那是学不好动态规划的,只有把握好基础并努力思考,不断开拓创新,才是学好它的关键。
出师表两汉:诸葛亮先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。
然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。
诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
宫中府中,俱为一体;陟罚臧否,不宜异同。
若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理;不宜偏私,使内外异法也。
侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下:愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。
将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰“能”,是以众议举宠为督:愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。
先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。
侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之、信之,则汉室之隆,可计日而待也。
臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。
先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。
后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
先帝知臣谨慎,故临崩寄臣以大事也。
受命以来,夙夜忧叹,恐托付不效,以伤先帝之明;故五月渡泸,深入不毛。
今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。
此臣所以报先帝而忠陛下之职分也。
至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。
若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏。
臣不胜受恩感激。
今当远离,临表涕零,不知所言。