备忘录技术

还是说矩阵连乘问题,在用动态规划来做的时候,是一种自底向上的路线,要接触m[1,n]就要先从一个矩阵的时候,2个连乘的时候,3个连乘的时候,开始一步步求,填好表,然后才可以求出n个矩阵连乘。

其实在想这道题目的时候,一般人们也会想用暴力的方法解决,就是用递归来做,算法就像下面这个样子

RECURSIVE-MATRIX-CHAIN(p, i, j)
1 if i = j
2     then return 0
3 m[i, j] ← ∞
4 for k ← i to j - 1
5      do q ← RECURSIVE-MATRIX-CHAIN(p, i, k)
                 + RECURSIVE-MATRIX-CHAIN(p,k + 1, j)
                 + pi-1 pk pj
6         if q < m[i, j]
7            then m[i, j] ← q
8 return m[i, j]

这个算法就是直接利用递归式


来写的,这个算法的时间复杂度是指数级别的,非常耗时,在下面的图中显示了这个递归算法的递归树


在图中可以看出,在递归过程中,有很多子问题是重复求的,浪费时间就是浪费在重复解了很多已经解决过的子问题。现在我们要做的就是,通过一个表来记录下已经求出来的那些子问题的解,然后在递归过程中,去检查要求解的子问题的值是否已经在表中记录,是的话,那么就不用去解,而是直接在表中读取即可,这就是备忘录技术,也是经常说的记忆化搜索。下面是利用备忘录技术修改的上面直接递归的代码

#include <iostream>
using namespace std;

#define INF 999999999
int m[101][101];

int LookUp_Chain(int p[],int i,int j)
{
	if(m[i][j] < INF)
		return m[i][j];
	if(i == j)
		m[i][j]=0;
	else
	{
		int q;
		for(int k=i;k<j;k++)
		{
			q=LookUp_Chain(p,i,k)+LookUp_Chain(p,k+1,j)+p[i-1]*p[k]*p[j];
			if(q < m[i][j])
				m[i][j]=q;
		}
	}
	return m[i][j];
}

int Memoized_Matrix_Chain(int p[],int n)
{
	n=n-1;
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j++)
			m[i][j]=INF;
	return LookUp_Chain(p,1,n);
}	

int main()
{
	int n;
	int p[101];
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>p[i];
	int _min=Memoized_Matrix_Chain(p,n);
	cout<<_min<<endl;
	return 0;
}


这个算法和用动态规划写的那个算法不同的就是,这个是采用自顶向下的思考方式,而动态规划的是采用自底向上的,但是两个算法的效率是相近的,都是O(n^3).这种技术也可以称为是动态规划的一种变形,有时解决一些问题时,这种方法写出来的算法会比用动态规划思想写出来的更容易理解。

上面这个代码是 POJ1651这道题的解答,前一篇日志也有写,是用动态规划的思想写的,大家可以对比一下。

POJ1651动态规划解题


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值