算法分析--动态规划--矩阵连乘

版权声明:版权归本作者所有,如需转载请务必注明出处及作者 https://blog.csdn.net/qq_35654046/article/details/84846905

动态规划算法的基本要素:

  1. 最优子结构性质

假设A1*A2*A3*...*An在k处断开为最优,那么只需要保证A1*...*Ak和Ak*..*An两个子序列的分割也是最优,就能保证该结果是最优。

  1. 子问题重叠性

问题描述:

对于多个矩阵连乘,不同的分割次序会导致计算次数的不同,所以要找到最优化的分割,减少计算量。

A1 A2 A3 A4 A5 A6
30*35 35*15 15*5 5*10 10*20 20*25

计算子问题的最优解并保存:

矩阵m保存子问题的最优计算量,矩阵s保存子问题的最优分割方式。

矩阵m:

矩阵s:

举例说明:

m[0][3]=7875,s[0][3]=1表示对于子问题(分割A1*A2*A3),需要的最少计算量为7875次,最优分割点在位置1,也就是分割为A1*(A2*A3)。

#include "stdafx.h"
#include<iostream>
#include<cstdlib>
using namespace std;
void MatrixChain(int *p, int n, int m[][6], int s[][6]);
void TraceBack(int i, int j, int s[][6]);

int main()
{
	int n = 6;
	int p[7] = { 30,35,15,5,10,20,25 };
	int m[6][6] = {};
	int s[6][6] = {};
	for (int i = 0; i < 6; i++)
		for (int j = 0; j < 6; j++)
		{
			m[i][j] = 0; s[i][j] = 0;
		}
	MatrixChain(p, n, m, s);
	for (int i = 0; i < 6; i++)
	{
		for (int j = 0; j < 6; j++) cout << s[i][j] << "\t";
		cout << endl;
	}
	//cout << s[0][5]<<endl;
	TraceBack(0, 5, s);
	system("pause");
	return 0;
}
//构造最优解矩阵
void MatrixChain(int *p, int n, int m[][6], int s[][6])
{
	for (int i = 0; i < n; i++) m[i][i] = 0;//将矩阵分割成单个的矩阵,此时计算量为0
	for (int r = 2; r <= n; r++)//将矩阵分割为2 - n 个矩阵,计算此时的计算量
		for (int i = 0; i < n-r+1; i++)	
		{
			int j = i + r - 1;
			//将矩阵连乘m[i][j]最优分割点初始化为第i个矩阵处
			m[i][j] = m[i + 1][j] + p[i] * p[i+1] * p[j+1];
			s[i][j] = i+1;
			//寻找比初始化分割点更优的分割点
			for (int k = i + 1; k <= j; k++)
			{
				int temp = m[i][k] + m[k + 1][j] + p[i] * p[k+1] * p[j+1];
				if (temp < m[i][j]){m[i][j] = temp;s[i][j] = k+1;}
			}
		}
}
//递归搜索最优解
void TraceBack(int i, int j, int s[][6])
{
	//查找最优解位置s[i][j]
	if (i == j || i == j-1) return;//已经分出来单个矩阵,或者两个矩阵相乘的部分,不需要再进行分割
	else
	{
		TraceBack(i, s[i][j] - 1, s);//递归分割左边部分
		cout << s[i][j] << "\t";//输出分割点位置
		TraceBack(s[i][j], j, s);//递归分割右边部分
	}	
}

参考资料

  1. 算法设计与分析--王晓东

猜你喜欢

转载自blog.csdn.net/qq_35654046/article/details/84846905