动态规划基本思想

基本要素:
(1)最优子结构性质
(2)重叠子问题性质
思想:
动态规划和分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
与分治法不同的是,动态规划法中分解得到的子问题不是互相独立的。若用分治法来解这类子问题,分解得到的子问题数目非常多,最后解决原问题需要耗费指数时间。但是这些子问题有很多是相同的,也就是同一个子问题被计算了很多次,不同子问题的数量可能只有多项式量级。
如果我们保存已经解决的子问题的解,需要解相同子问题时找出已经计算出的解,这样可以减少大量重复计算,最终得到多项式时间算法。
经常用一个来记录所有已解决的子问题的解。不管该子问题以后是否被利用,只要它被计算过,就将其结果填入表中。这就是动态规划的基本思想。具体的动态规划算法多种多样,但它们具有相同的填表格式

—(计算机算法设计与分析 第四版 王晓东)—
####动态规划例子:(矩阵连乘问题)
给定N个矩阵{A1,A2,A3,An},其中Ai与A(i+1)是可以相乘的,考察这N个矩阵的连乘积A1A2,An。
由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定,比如下面4个矩阵的连乘积。
A1,A2, A3, A4
1,(2,(3,4))
1,((2,3),4)
(1,2),(3,4)
(1,(2,3)),4
((1,2),3),4

#####最优解的结构
计算A[1:n]的最优次序所包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的。
A[1:n] = A[1:k] * A[K+1:n] 其中 ( 1 < k < n)
递推关系如下:
m(i , j) = 0 ,(i=j)
m(i , j) = min{ m(i,k) + m(k+1,j) + P(i-1)P(k)P(j) } ,(i < j )
#####重叠子问题
重叠的子问题主要体现在m表格里,

例题:我们计算如下6个矩阵的连乘积,
A1 ------ A2 ------ A3 ----- A4 ----- A5 ----- A6
(3035) (3515) (155) (510) (1020) (2025)

const int N = 6;
int table[N + 1][N + 1];
int p[N + 1] = { 30, 35, 15, 5, 10, 20, 25 };
void MatrixMulti()
{
	for (int r = 2; r <= N; r++) //r表示连乘矩阵的个数
	{
		for (int i = 1; i <= N - r + 1; i++) //i表示起始矩阵索引
		{
			int j = i + r - 1; //j表示终止矩阵索引
			for (int k = i; k < j; k++)
			{
				int temp = table[i][k] + table[k+1][j] + p[i - 1] * p[k] * p[j];
				table[i][j] = (table[i][j] == 0) ? temp : min(table[i][j], temp);
			}
		}
	}
}
int main()
{
	MatrixMulti();
	cout << "最小乘积为:" <<table[1][N] << endl;
	return 0;
}
/*输出结果:
最小乘积为:15125
table数组内容为:
0       0       0       0       0       0       0
0       0       15750   7875    9375    11875   15125
0       0       0       2625    4375    7125    10500
0       0       0       0       750     2500    5375
0       0       0       0       0       1000    3500
0       0       0       0       0       0       5000
0       0       0       0       0       0       0

*/

你可能感兴趣的:(数据结构与算法)