动态规划解决矩阵连乘问题(C++实现)

1.       采用标准的矩阵乘法来计算M1M2M3三个矩阵的乘积M1M2M3,设这三个矩阵的维数分别是2 × 10、10 × 2和2 × 10。如果先把M1M2相乘,然后把结果和M3相乘,那么要进行2× 10 × 2 + 2 × 2 × 10 = 80次乘法;如果代之用M2M3相乘的结果去乘M1,那么数量乘法的次数为10× 2 × 10 + 2 × 10 × 10 = 400。显然,执行乘法M1(M2M3)耗费的时间是执行乘法(M1M2)M3的5倍。一般来说,n个矩阵M1M2……Mn链乘法的耗费,取决于n– 1个乘法执行的顺序,请设计一个动态规划算法,使得计算矩阵链乘法时需要的数量乘法次数达到最小。

矩阵

M1

M2

M3

M4

M5

M6

维数

30 × 35

35 × 15

15 × 5

5 × 10

10 × 20

20 × 25

由于问题中存在大量的重叠子问题,使用分治算法递归得出结果的效率并不高,因此可以使用动态规划来解决。首先创建一个函数functionD(参数为p数组:用于存放矩阵的行列数,n:矩阵的规模,二维数组m用来存放指定范围矩阵相乘的次数最小值,二维数组s:用于存放指定范围矩阵的最佳断开位置),首先使用for循环将单个矩阵相乘的次数设为零,其次通过使用for循环来控制矩阵的规模,使其规模递增,在一个规模里将默认的断点设为第一个矩阵处断开,其次再使用for循环控制断点的移动,然后通过if语句来得出是否为最佳断点。当所有规模都循环结束时,得到的m[i][n]便是整个矩阵链的最短乘法次数。

#include <iostream>

using namespace std;


 void functionD(int *p,int n,int **m,int **s) {
	for (int i=1 ; i <= n; i++){
		m[i][i]=0;//将单个矩阵相乘的次数设为0 
	} 
	for(int r=2 ; r <= n; r++) {//r为矩阵链的规模 
		for(int i=1; i<=n-r+1;i++){//i为前边界 
			int j=i+r-1;//j为后边界 
			m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];//记录断点在i处时所需要的乘法次数 
			s[i][j]=i;//将断点初始化在i处 
			for(int k=i+1;k<j;k++){
				int t=m[i][k]/*实现重叠子问题的利用*/+m[k+1][j]+p[i-1]*p[k]*p[j];
				if(t<m[i][j]) {//如果新的断点的乘法次数小于原来的次数 
					m[i][j]=t;//更新最少乘法次数 
					s[i][j]=k;//保存最佳断点位置 
				}
			} 
		}
	}
}
int main(){
	int p[] = {30,35,15,5,10,20,25};//矩阵链的行列数 
	int n=6;//矩阵的个数 
	int **m,**s;
	m=new int *[n];
	for(int i=0;i<n;i++){
		m[i]=new int [n];
	}  
	s=new int *[n];
	for(int i=0;i<n;i++){
		s[i]=new int [n];
	}
	 functionD(p,n,m,s) ; 
	cout<<"最少乘法次数为"<<m[1][n]<<endl;
	return 0;
}

    原文作者:动态规划
    原文地址: https://blog.csdn.net/CWH0908/article/details/79889302
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞