第6讲动态规划专题讲座.docx
- 文档编号:5352692
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:46
- 大小:136.96KB
第6讲动态规划专题讲座.docx
《第6讲动态规划专题讲座.docx》由会员分享,可在线阅读,更多相关《第6讲动态规划专题讲座.docx(46页珍藏版)》请在冰豆网上搜索。
第6讲动态规划专题讲座
第6章动态规划
6.1动态规划概述
动态规划是运筹学的一个分支,是求解决策过程最优化的数学方法。
20世纪50年代美国数学家贝尔曼(RechardBellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优性原理,把多阶段决策过程转化为一系列单阶段问题逐个求解,创立了解决多阶段过程优化问题的新方法——动态规划。
动态规划问世以来,在经济管理、生产调度、工程技术和最优控制等方面得到了广泛的应用。
例如最短路线、库存管理、资源分配、装载等问题,用动态规划方法比用其它方法求解更为方便。
6.1.1动态规划的概念
动态规划所处理的对象是多阶段决策问题。
多阶段决策问题,是指这样的一类特殊的活动过程,问题可以分解成若干相互联系的阶段,在每一个阶段都要做出决策,形成一个决策序列,该决策序列也称为一个策略。
对于每一个决策序列,可以在满足问题的约束条件下用一个数值函数(即目标函数)衡量该策略的优劣。
多阶段决策问题的最优化求解目标是获取导致问题最优值的最优决策序列(最优策略),即得到最优解。
例6.1已知6种物品和一个可载重量为60的背包,物品i(i=1,2,…,6)的重量分别为(15,17,20,12,9,14),产生的效益分别为(32,37,46,26,21,30)。
在装包时每一件物品可以装入,也可以不装,但不可拆开装。
确定如何装包,使所得装包总效益最大。
这就是一个多阶段决策问题,装每一件物品就是一个阶段,每一个阶段都要有一个决策:
这一件物品装包还是不装。
这一装包问题的约束条件为:
目标函数为:
对于这6个阶段的问题,如果每一个阶段都面临2个选择,则共存在26个决策序列。
应用贪心算法,按单位重量的效益从大到小装包,得第1件与第6件物品不装,依次装第5、3、
2、4件物品,这就是一个决策序列,或简写为序列(0,1,1,1,1,0),该策略所得总效益为130。
第1件与第4件物品不装,第2、3、5、6件物品装包,或简写为序列(0,1,1,0,1,1),这一决策序列的总载重量为60,满足约束条件,使目标函数即装包总效益达最大值134,即最优值为134。
因而决策序列(0,1,1,0,1,1)为最优决策序列,即最优解,这是应用动态规划求解的目标。
在求解多阶段决策问题中,各个阶段的决策依赖于当时的状态并影响以后的发展,即引起状态的转移。
一个决策序列是随着变化的状态而产生的。
应用动态规划设计使多阶段决策过程达到最优(成本最省,效益最高,路径最短等),依据动态规划最优性原理:
“作为整个过程的最优策略具有这样的性质,无论过去的状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略”。
也就是说,最优决策序列中的任何子序列都是最优的。
“最优性原理”用数学语言描述:
假设为了解决某一多阶段决策过程的优化问题,需要依次作出n个决策D1,D2,…,Dn,如若这个决策序列是最优的,对于任何一个整数k,1 最优性原理体现为问题的最优子结构特性。 当一个问题的最优解中包含了子问题的最优解时,则称该问题具有最优子结构特性。 最优子结构特性使得在从较小问题的解构造较大问题的解时,只需考虑子问题的最优解,从而大大减少了求解问题的计算量。 最优子结构特性是动态规划求解问题的必要条件。 例如,在以后案例中求得在数字串847313926中插入5个乘号,使乘积最大的最优解为: 8*4*731*3*92*6=38737152 该最优解包含了在84731中插入2个乘号使乘积最大,插入方式为8*4*731; 在7313中插入1个乘号使乘积最大,插入方式为731*3; 在3926中插入2个乘号使乘积最大,插入方式为3*92*6。 这些子问题的最优解,这就是最优子结构特性。 最优性原理是动态规划的基础。 任何一个问题,如果失去了这个最优性原理的支持,就不可能用动态规划设计求解。 能采用动态规划求解的问题都需要满足以下条件: (1)问题中的状态必须满足最优性原理; (2)问题中的状态必须满足无后效性。 所谓无后效性是指: “下一时刻的状态只与当前状态有关,而和当前状态之前的状态无关,当前状态是对以往决策的总结”。 6.1.2动态规划实施步骤 动态规划求解最优化问题,通常按以下几个步骤进行。 (1)把所求最优化问题分成若干个阶段,找出最优解的性质,并刻划其结构特性。 最优子结构特性是动态规划求解问题的必要条件,只有满足最优子结构特性的多阶段决策问题才能应用动态规划设计求解。 (2)将问题发展到各个阶段时所处不同的状态表示出来,确定各个阶段状态之间的递推(或递归)关系,并确定初始(边界)条件。 通过设置相应的数组表示各个阶段的最优值,分析归纳出各个阶段状态之间的转移关系,是应用动态规划设计求解的关键。 (3)应用递推(或递归)求解最优值。 递推(或递归)计算最优值是动态规划算法的实施过程。 具体应用与所设置的表示各个阶段最优值的数组密切相关。 (4)根据计算最优值时所得到的信息,构造最优解。 构造最优解就是具体求出最优决策序列。 通常在计算最优值时,根据问题具体实际记录更多的信息,根据所记录的信息构造出问题的最优解。 以上步骤前3个是动态规划设计求解最优化问题的基本步骤。 当只需求解最优值时,第4个步骤可以省略。 若需求出问题的最优解,则必须执行第4个步骤。 6.2最长子序列探索 本节应用动态规划探索两个典型的子序列问题: 最长非降子序列与两个序列的最长公共子序列。 6.2.1最长非降子序列 1.案例提出 给定一个由n个正整数组成的序列,从该序列中删除若干个整数,使剩下的整数组成非降子序列,求最长的非降子序列。 例如,由12个正整数组成的序列为: 48,16,45,47,52,46,36,28,46,69,14,42 请在序列中删除若干项,使剩下的项为非降(即后面的项不小于后面的项)序列,剩下的非降序列最长为多少项? 2.递推实现动态规划设计 设序列的各项为a[1],a[2],…,a[n](可随机产生,也可从键盘依次输入),对每一个整数操作为一个阶段,共为n个阶段。 (1)建立递推关系 设置b数组,b[i]表示序列的第i个数(保留第i个数)到第n个数中的最长非降子序列的长度,i=1,2,…,n。 对所有的j>i,比较当a[j]≥a[i]时的b[j]的最大值,显然b[i]为这一最大值加1,表示加上a[i]本身这一项。 因而有递推关系: b[i]=max(b[j])+1(a[j]≥a[i],1≤i 边界条件: b[n]=1 (2)逆推计算最优值 b[n]=1; for(i=n−1;i>=1;i−−) {max=0;for(j=i+1;j<=n;j++) if(a[i]<=a[j]&&b[j]>max) max=b[j]; b[i]=max+1;//逆推得b[i] } 逆推依次求得b[n−1],…,b[1],比较这n−1个值得其中的最大值lmax,即为所求的最长非降子序列的长度即最优值。 (3)构造最优解 从序列的第1项开始,依次输出b[i]分别等于lmax,lmax−1,…,1的项a[i],这就是所求的一个最长非降子序列。 (4)递推实现动态规划程序设计 //递推实现动态规划 #include #include #include voidmain() {inti,j,n,t,x,max,lmax,a[2000],b[2000]; t=time(0)%1000;srand(t);//随机数发生器初始化 printf("inputn(n<2000): "); scanf("%d",&n); for(i=1;i<=n;i++) {a[i]=rand()%(5*n)+10;//产生并输出n个数组成的序列 printf("%d",a[i]); } b[n]=1;lmax=0; for(i=n-1;i>=1;i--)//逆推求最优值lmax {max=0; for(j=i+1;j<=n;j++) if(a[i]<=a[j]&&b[j]>max) max=b[j]; b[i]=max+1;//逆推得b[i] if(b[i]>lmax)lmax=b[i];//比较得最大非降序列长 } printf("\nL=%d.\n",lmax);//输出最大非降序列长 x=lmax; for(i=1;i<=n;i++) if(b[i]==x) {printf("%d",a[i]);x--;}//输出一个最大非降序列 } 3.递归实现动态规划设计 (1)建立递归关系 设q(i)表示序列的第i个数(保留第i个数)到第n个数中的最长非降子序列的长度,i=1,2,…,n。 对所有的j>i,比较当a[j]≥a[i]时的q(j)的最大值,显然q(i)为这一最大值加1,表示加上a[i]本身这一项。 因而有递归关系: q(i)=max(q(j))+1(a[j]≥a[i],1≤i 递归出口: q(n)=1 (2)递归函数设计 intq(inti) {intj,f,max; if(i==n)f=1; else {max=0; for(j=i+1;j<=n;j++) if(a[i]<=a[j]&&q(j)>max) max=q(j); f=max+1; } returnf; } (3)在主函数中依次调用q(n−1),…,q (1),比较这n−1个值得其中的最大值lmax,即为所求的最长非降子序列的长度即最优值。 (4)构造最优解 从序列的第1项开始,依次输出q(i)分别等于lmax,lmax−1,…,1所那就的项a[i],这就是所求的一个最长非降子序列。 (5)递归实现动态规划程序设计 //递归实现动态规划 #include #include #include inti,n,a[2000]; voidmain() {intt,x,lmax;intq(inti); t=time(0)%1000;srand(t);//随机数发生器初始化 printf("inputn(n<2000): "); scanf("%d",&n); for(i=1;i<=n;i++) {a[i]=rand()%(5*n)+10;//产生并输出n个数组成的序列 printf("%d",a[i]); } lmax=0; for(i=n-1;i>=1;i--) if(q(i)>lmax)lmax=q(i);//比较得最大非降序列长 printf("\nL=%d.\n",lmax);//输出最大非降序列长 x=lmax; for(i=1;i<=n;i++) if(q(i)==x) {printf("%d",a[i]);x--;}//输出一个最大非降序列 } 4.程序运行示例与讨论 运行程序,inputn(n<2000): 12 481645475246362846691442 L=5. 1645475269 注意,所给序列长度为5的非降子序列可能有多个,这里只输出其中一个。 由上可知,在动态规划设计中,最优值可经递推得到,也可经递归得到。 一般地,应用递推效率更高些,以下各案例的动态规划设计中均应用递推得最优值。 6.2.2最长公共子序列 一个给定序列的子序列是在该序列中删去若干个元素后所得到的序列。 用数学语言表述, 给定序列 ,另一序列 ,X的子序列是指存在一个严格递增 下标序列 使得对于所有j=1,2,…,k有 。 例如,序列 是序列 的一个子序列,或按紧凑格式书写,序列“bdca”是“abcdcba”的一个子序列。 若序列Z是序列X的子序列,又是序列Y的子序列,则称Z是序列X与Y的公共子序列。 例如,序列“bcba”是“abcbdab”与“bdcaba”的公共子序列。 1.案例提出 给定两个序列 和 ,找出序列X和Y的最长 公共子序列。 例如,给出序列X: hsbafdreghsbacdba与序列Y: acdbegshbdrabsa,这两个序列的最长公共子序列如何求得? 2.动态规划算法设计 求序列X与Y的最长公共子序列可以使用穷举法: 列出X的所有子序列,检查X的每一个子序列是否也是Y的子序列,并记录其中公共子序列的长度,通过比较最终求得X与Y的最长公共子序列。 对于一个长度为m的序列X,其每一个子序列对应于下标集{1,2,…,m}的一个子集,即X的子序列数目多达2m个。 由此可见应用穷举法求解是指数时间的。 最长公共子序列问题具有最优子结构性质,应用动态规划设计求解。 (1)建立递推关系 设序列 和 的最长公共子序列为 , 与 (i=0,1,…,m;j=0,1,…,n)的最长公共子序列的长度为c(i,j)。 若i=m+1或j=n+1,此时为空序列,c(i,j)=0(边界条件)。 若x (1)=y (1),则有z (1)=x (1),c(1,1)=c(2,2)+1(其中1为z (1)这一项); 若x (1)≠y (1),则c(1,1)取c(2,1)与c(1,2)中的最大者。 一般地,若x(i)=y(j),则c(i,j)=c(i+1,j+1)+1; 若x(i)≠y(j),则c(i,j)=max(c(i+1,j),c(i,j+1))。 因而归纳为递推关系: 边界条件: c(i,j)=0(i=m+1或j=n+1) (2)逆推计算最优值 根据以上递推关系,逆推计算最优值c(0,0)流程为: for(i=0;i<=m;i++)c[i][n]=0;//赋初始值 for(j=0;j<=n;j++)c[m][j]=0; for(i=m−1;i>=0;i−−)//计算最优值 for(j=n−1;j>=0;j−−) if(x[i]==y[j]) c[i][j]=c[i+1][j+1]+1; elseif(c[i][j+1]>c[i+1][j]) c[i][j]=c[i][j+1]; elsec[i][j]=c[i+1][j]; printf("最长公共子串的长度为: %d",c[0][0]);//输出最优值 以上算法时间复杂度为O(mn)。 (3)构造最优解 为构造最优解,即具体求出最长公共子序列,设置数组s(i,j),当x(i)=y(j)时s(i,j)=1;当x(i)≠y(j)时s(i,j)=0。 X序列的每一项与Y序列的每一项逐一比较,根据s(i,j)与c(i,j)取值具体构造最长公共子序列。 实施x(i)与y(j)比较,其中i=0,1,…,m−1;j=t,1,…,n−1;变量t从0开始取值,当确定最长公共子序列一项时,t=j+1。 这样处理可避免重复取项。 若s(i,j)=1且c(i,j)=c(0,0)时,取x(i)为最长公共子序列的第1项; 随后,若s(i,j)=1且c(i,j)=c(0,0)−1时,取x(i)最长公共子序列的第2项; 一般地,若s(i,j)=1且c(i,j)=c(0,0)−w时(w从0开始,每确定最长公共子序列的一项,w增1),取x(i)最长公共子序列的第w项。 构造最长公共子序列描述: for(t=0,w=0,i=0;i<=m−1;i++) for(j=t;j<=n−1;j++) if(s[i][j]==1&&c[i][j]==c[0][0]−w) {printf("%c",x[i]); w++;t=j+1;break; } (4)算法的复杂度分析 以上动态规划算法的时间复杂度为O(n2)。 3.最长公共子序列C程序实现 //最长公共子序列 #include #defineN100 voidmain() {charx[N],y[N]; inti,j,m,n,t,w,c[N][N],s[N][N]; printf("请输入序列x: ");//先后输入序列 scanf("%s",x); printf("请输入序列y: ");scanf("%s",y); for(m=0,i=0;x[i]! ='\0';i++)m++; for(n=0,i=0;y[i]! ='\0';i++)n++; for(i=0;i<=m;i++)c[i][n]=0;//赋边界值 for(j=0;j<=n;j++)c[m][j]=0; for(i=m−1;i>=0;i−−)//递推计算最优值 for(j=n−1;j>=0;j−−) if(x[i]==y[j]) {c[i][j]=c[i+1][j+1]+1; s[i][j]=1; } else {s[i][j]=0; if(c[i][j+1]>c[i+1][j]) c[i][j]=c[i][j+1]; elsec[i][j]=c[i+1][j]; } printf("最长公共子序列的长度为: %d",c[0][0]);//输出最优值 printf("\n最长公共子序列为: ");//构造最优解 t=0;w=0; for(i=0;i<=m−1;i++) for(j=t;j<=n−1;j++) if(s[i][j]==1&&c[i][j]==c[0][0]−w) {printf("%c",x[i]); w++;t=j+1;break; } printf("\n"); } 运行程序示例: 请输入序列x: hsbafdreghsbacdba 请输入序列y: acdbegshbdrabsa 最长公共子序列的长度为: 9 最长公共子序列为: adeghbaba 6.3最优路径搜索 本节应用动态规划探讨两类最优路径搜索问题,一类是点数值路径,即连接成路径的每一个点都带有一个数值;另一类是边数值路径,即连接成路径的每一条边都带有一个数值。 6.3.1点数值三角形的最优路径搜索 点数值三角形是一个二维数阵: 三角形由n行构成,第k行有k个点,每一个点都带有一个数值数。 点数值三角形的数值可以随机产生,也可从键盘输入。 最优路径通常由路径所经各点的数值和来确定。 1.案例提出 在一个n行的点数值三角形中,寻找从顶点开始每一步可沿左斜(L)或右斜(R)向下至底的一条路径,使该路径所经过的点的数值和最小。 图6.17行点数值三角形 例如,n=7时给出的点数值三角形如图6.1所示,如何寻找从项到底的数值和最小路径? 该最优路径的数值和为多少? 2.动态规划算法设计 设点数值三角形的数值存储在二维数组a(n,n)。 (1)建立递推关系 设数组b(i,j)为点(i,j)到底的最小数值和,字符数组stm(i,j)指明点(i,j)向左或向右的路标。 b(i,j)与stm(i,j)(i=n−1,…,2,1)的值由b数组的第i+1行的第j个元素与第j+1个元素值的大小比较决定,即有递推关系: b(i,j)=a(i,j)+b(i+1,j+1);stm(i,j)=“R”(b(i+1,j+1) b(i,j)=a(i,j)+b(i+1,j);stm(i,j)=“L”(b(i+1,j+1)≥b(i+1,j)) 其中i=n−1,…,2,1 边界条件: b(n,j)=a(n,j),j=1,2,…,n。 所求的最小路径数值和即问题的最优值为b(1,1)。 (2)逆推计算最优值 for(j=1;j<=n;j++)b[n][j]=a[n][j]; for(i=n−1;i>=1;i−−)//逆推得b[i][j] for(j=1;j<=i;j++) if(b[i+1][j+1] {b[i][j]=a[i][j]+b[i+1][j+1];stm[i][j]='R';} else {b[i][j]=a[i][j]+b[i+1][j];stm[i][j]='L';} Printf("%d",b(1,1)); (3)构造最优解 为了确定与并输出最小路径,利用stm数组从上而下查找: 先打印a(1,1),若stm(1,1)=“R”,则下一个打印a(2,2),否则打印a(2,1)。 一般地,在输出i循环(i=2,3,…,n)中: 若stm(i−1,j)=“R”则打印“−R−”;a(i,j+1);同时赋值j=j+1。 若stm(i−1,j)=“L”则打印“−L−”;a(i,j); 依此打印出最小路径,即所求的最优解. (4)算法的复杂度分析 以上动态规划算法的时间复杂度为O(n2),空间复杂度也为O(n2)。 2.最小路径寻求与测试程序设计 //点数值三角形的最小路径 #include #include #include voidmain() {intn,i,j,t; inta[50][50],b[50][50];charstm[50][50]; printf("请输入数字三角形的行数n: "); scanf("%d",&n); t=time(0)%1000;srand(t);//随机数发生器初始化 for(i=1;i for(i=1;i<=n;i++) {for(j=1;j<=36-2*i;j++)printf(""); for(j=1;j<=i;j++) {a[i][j]=rand()/1000+1; printf("%4d",a[i][j]);//产生并打印n行数字三角形 } printf("\n"); } printf("请在以上点数值三角形中从顶开始每步可左斜或右斜至底"); printf("寻找一条数字和最小的路径.\n"); for(j=1;j<=n;j++)b[n][j]=a[n][j]; for(i=n-1;i>=1;i--)//逆推得b[i][j] for(j=1;j<=i;j++) if(b[i+1][j+1] {b[i][j]=a[i][j]+b[i+1][j+1];stm[i][j]='R';} else{b[i][j]=a[i][j]+b[i+1][j];stm[i][j]='L';} printf("最小路径和为: %d\n",b[1][1]);//输出最小数字和 printf("最小路径为: %d",a[1][1]);j=1;//输出和最小的路径 for(i=2;i<=n;i++) if(stm[i-1][j]=='R') {printf("-R-%d",a[i][j+1]);j++;} else printf("-L-%d",a[
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第6讲 动态规划专题讲座 动态 规划 专题讲座
![提示](https://static.bdocx.com/images/bang_tan.gif)