算法学习之动态规划(求矩阵连乘最小相乘次数)

0 阅读 作者:逆天96 2017-10-17

 基本思想:动态规划算法与分治法类似,其基本思想是将带求解的问题划分成若干个独立子问题,根据求得子问题的解合并而得到原问题的解。而动态规划划分的子问题往往不是相互独立的,因此若采用同分治法相同的求解问题的方法会导致大量的子问题被重复计算,为了避免这种情况发生,我们可以用一个表来记录我们求得的子问题的解,无论该子问题的解以后是否会用到,只要被计算,就将其填入表中。这便是动态规划的基本思想。


求解的基本步骤

(1)找出最优解的性质,并刻画其结构特征。

(2)递归的定义最优值。

(3)以自底向上的方式计算出最优值。

(4)根据计算最优值时得到的信息,构造最优解。


时间、精力和水平有限,无法给出专业详细地分析,但我会把自己掌握的部分毫无保留分享给大家。

下面的程序我尽可能给出最详细的注释,如有错误还请及时指出,以避免产生没必要的误会。

#include <iostream>
//数组p存储连乘矩阵的维数
int p[] = { 30, 35, 35, 15, 15, 5, 5, 10, 10, 20, 20, 25 };
int pcount = sizeof(p) / sizeof(*p);
//二维数组m存放所有子问题的最优值
int m[6][6];
//二维数组s存放断开的位置k
int s[6][6];
//用于打印二维数组
void debug(int array[][6]);
//预初始化二维数组
void initialization(int array[][6]);
//打印最优解的构成
void Traceback(int i, int j, int array[][6]);
//根据自底向上的方式计算所有子问题最优值
void MatrixChain(int *p, int n, int m[][6], int s[][6])
{
	initialization(m);	
	initialization(s);	
	//注意n/2得到的是相乘矩阵的个数	
	for (int i = 0; i < n/2; i++) m[i][i] = 0;    //单个矩阵最优值为0	
	//外层循环,从矩阵A1-A5依次计算矩阵链长度为2,3,4,5	
	for (int r = 1; r < n/2;r++)	
		//内层循环,计算矩阵链长度为x(x可能为2,3,4,5)的所有值(例如:若x=2,
		//则计算m[1][2],m[2][3],m[3][4],m[4][5],m[5][6])	
	for (int i = 0; i < n/2 - r; i++)
		//随矩阵链长度x增加,i的最大值与(n/2-r)	                                 
		//构成对应关系	
	{		
		int j = i + r;							//列数j取决于矩阵链长度和行数i		
		m[i][j] = m[i + 1][j] + p[2 * i] * p[2 * i + 1] * p[j * 2 + 1];		
		//这里先求出一个基本解,以A0矩阵划分(A[0]*A[1:5])		
		//std::cout << "m"<<"["<<i<<"]"<<"["<<j<<"]"<<m[i][j] << std::endl;		
		s[i][j] = i;							//保存划分的位置,Trackback求最优解用到		
		for (int k = i + 1; k < j; k++)			//对每个可能划分的位置进行检索		
		{			
			int t = m[i][k] + m[k + 1][j] + p[2 * i] * p[2 * k + 1] * p[2 * j + 1];     //求最优值的递推式			
		//如果计算得到的值比基本解更优,那么替换原来的最优值和划分位置			
		if (t < m[i][j]) { m[i][j] = t; s[i][j] = k;}		
		}	
	}

}
void debug(int array[][6])
{
	for (int i = 0; i < 6; i++)	
	{
		for (int j = 0; j < 6; j++)			
		std::cout << array[i][j] << " ";		
		std::cout << std::endl;	
	}
}

void initialization(int array[][6])
{	
	for (int i = 0; i < 6; i++)	
		for (int j = 0; j < 6; j++)		
		array[i][j] = -1;
}

void Traceback(int i, int j, int array[][6])
{	
	using std::cout;	
	using std::endl;	
	if (i == j) return;	
	Traceback(i, array[i][j], array);	
	Traceback(array[i][j] + 1, j, array);	
	cout << "Multiply A" << i << "," << array[i][j];	
	cout << " and A" << (array[i][j] + 1) << "," << j << endl;
}

//一小段测试程序,不懂请尽可能多调试以便理解。
int main()
{	
	MatrixChain(p, pcount, m, s);	
	debug(m);	
	//debug(s);	
	Traceback(1, 5, s);	
	return 0;
}

本文出自 “timefriend” 博客,请务必保留此出处http://bocaihaoci.blog.51cto.com/12164980/1867205

原文地址:http://bocaihaoci.blog.51cto.com/12164980/1867205
广告一下
热门教程
PHP7报A non well formed numeric value encountered 0
Linux系统下关闭mongodb的几种命令分享 0
mongodb删除数据、删除集合、删除数据库的命令 0
Git&Github极速入门与攻坚实战课程 0
python爬虫教程使用Django和scrapy实现 0
libnetsnmpmibs.so.31: cannot open shared object file 0
数据结构和算法视频教程 0
redis的hash结构怎么删除数据呢? 0
C++和LUA解析器的数据交互实战视频 0
mongodb errmsg" : "too many users are authenticated 0
C++基础入门视频教程 0
用30个小时精通C++视频教程可能吗? 0
C++分布式多线程游戏服务器开发视频教程socket tcp boost库 0
C++培训教程就业班教程 0
layui的util工具格式时间戳为字符串 0
C++实战教程之远程桌面远程控制实战 1
网络安全培训视频教程 0
LINUX_C++软件工程师视频教程高级项目实战 0
C++高级数据结构与算法视频教程 0
跨域问题很头疼?通过配置nginx轻松解决ajax跨域问题 0
相关文章
【译】JavaScript数据结构(3):单向链表与双向链表 16
10个JavaScript难点 16
【译】苹果拒绝支持PWA,有损Web的未来 16
iView 一周年了,同时发布了 2.0 正式版,但这只是开始... 16
nodejs+mongodb构建一个简单登录注册功能 16
【译】JavaScript数据结构(4):树 16
组件化开发与黑箱 16
TypeScript - 不止稳,而且快 16
webpack3+anujs+ReactCSSTransitionGroup 16
原生js实现图片放大镜效果 16
WEB缓存探究第二弹——实战 16
纯笔记:vfork 的一些使用场景(顺便讲一下 fork 的原理) 16
Android APP 内部捐赠实现(支付宝&amp;微信) 16
WKWebView 的一些小总结 16
模型评价(一) AUC大法 16
开始使用GraphQL 16
Webpack模块化原理简析 16
gulp使用问题记录 16
使用Angular4动画为页面添彩 16
Python27 Matplotlib (win64 python2.7) 安装及简单使用 16