动态规划算法总结

       动态规划的基本思想

        动态规划算法的基本思想是将代求解的的问题分为若干子问题,先求解子问题,再利用子问题的解得到原问题的解,这就要求问题整体的解一定也是局部的最优解。若用分治法求解时,有些子问题被重复计算了多次,如果能够保存子问题的答案,在求规模更大的问题的解的时候可以再利用以求得的答案,就可以避免大量重复计算。动态规划的本质思想是利用子问题求解原问题。这样就衍生出了两种解决问题的方法,一种是自顶向下递归式解决问题,这种方法代码书写简单,往往写出状态转移方程问题就能解决。但缺点是重复计算子问题,导致时间开销过大,并且不容易找到解的最优路径。于是我们介绍第二种动态规划问题的解决方法:自底向上的迭代式解决方法。此方法也是解决动态规划的常用方法,可以很清晰地求出最优解,难点在于将状态转移方程转化为迭代过程,下面我们介绍第二种动态规划解决方法:

       动态规划问题求解步骤:

1、找出最优解的性质,刻画其结构特征

2、递归式地定义最优值,找到状态转移方程,这一步是核心

3、以自底向上的方式计算最优值

4、根据计算最优值时的到的信息构造最优解


下面我们以矩阵连乘问题为例说明动态规划算法的设计思想:

矩阵连乘问题

问题描述:给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10*100,100*5和5*50,采用(A1A2)A3,乘法次数为10*100*5+10*5*50=7500次,而采用A1(A2A3),乘法次数为100*5*50+10*100*50=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次。

加括号的方式对计算量有很大的影响,于是自然地提出矩阵连乘的最优计算次序问题,即对于给定的相继n个矩阵,如何确定矩阵连乘的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。


穷举搜索法是最容易想到的,也就是列举所有可能的计算次序,选择乘法次数最少的。这样做计算量太大,设不同的计算次序有P(n),可以得到P(n)的递推式如下:

解此递归方程可得P(n)实际上是个卡特兰数,也就是说P(n)是随着n的增长呈指数增长的,显然穷举法不是一个好的方法。


下面我们介绍动态规划算法:

1、分析最优解结构

2、建立递归关系

设计算A[i:j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]。
当i=j时,A[i:j]=Ai,因此,m[i][i]=0,i=1,2,…,n
当i<j时,若A[i:j]的最优次序在Ak和Ak+1之间断开,i<=k<j,则:m[i][j]=m[i][k]+m[k+1][j]+pi-1pkpj。由于在计算是并不知道断开点k的位置,所以k还未定。不过k的位置只有j-i个可能。因此,k是这j-i个位置使计算量达到最小的那个位置。

综上,有递推关系如下:

3、计算最优值

递归的代码如下:

int b[100][100];//存i到j连乘最优解 
int a[100];
int dp(int i,int j)
{
	if(j==i)
	{
		return 0;
	}
	else
	{
		int min1=MAX;
		for(int k=i;k<j;k++)
		{
			int min2=dp(i,k)+dp(k+1,j)+a[i]*a[k+1]*a[j+1];
			min1=min(min1,min2);
			
		}
		return min1;
	}
}

 简单的递归非常耗费时间

下面是自底向上迭代求解:

我们给出下面六个矩阵

借助填表理解自底向上迭代求解的方法

填表过程是按对角线填写的,只利用到了二维数组的右上角一部分。

根据地推公式,我们可以知道,在i=j时m=0,所以先构造出最长的对角线部分的数据,如下图:

继续构造:

m(1,2)=min{m[1][1]+m[2][2]+p0p1p2}={0+0+303515}=15750

m(2,3) = min(m[2][2]+m[3][3]+p1p2p3=0+0+35155)=2625

. . . 

注意求解时有多个划分,注意取最小值

最终得到的表格如下

我们要的结果在右上角15125

4、构造最优解

动态规划的第四步是构造最优解,上面算法只是计算出了最优值,并未给出最优解。但是状态转移方程结合图表已经给出了构造最优解需要的全部信息。用s[i][j]记录矩阵链a[i][j]之间最佳切割方式,假设最优切割点是k,那么只需要求s[i][k],s[k+1][j]的值便可,如此往后计算。

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值