动态规划算法——矩阵乘法的顺序安排
2013-05-26 15:59
169 查看
动态是解决递归过程的大量冗余计算的缺点,其采用把子问题的答案系统的记录在一个表中,当计算后面的问题是用到前面的结果可以直接到表中查找,而无需再递归重新计算。
比如:斐波那契数是一个常见的递归计算过程,采用递归算法程序效率非常低。递归算法是模仿递归过程的,计算F(n),存在一个对F(n-1)和F(n-2)的调用,求解F(n-1),要对F(n-2)、F(n-3)的调用,存在2次对F(n-2)的计算、F(n-3)计算3次,F(n-4)计算5次等等。随着n的增大,对底层的计算次数呈现指数增长。其实计算F(n)时只要F(n-1)和F(n-2),因此只要记录最近计算的两个斐波那契数就OK。动态规划的思想就是把底层计算的结果存储以供上一层计算时使用,这样就避免了重复的计算。
下面介绍动态规划如何用于解决矩阵乘法的顺序安排问题:
例子:4个矩阵A、B、C、D,大小分别为:50*10、10*40、40*30、30*5,乘积ABCD可以任意加括号在计算其值。不同的计算顺序乘法次数不一样。
(A((BC)D)):16000次乘法;(A(B(CD))):10500次乘法;((AB)(CD)):36000次乘法;(((AB)C)D):87500次乘法;((A(BC))D):34500次乘法。
找到最优的计算次序可以有效的降低计算量。
给定矩阵A1,A2,...An,如何找到其计算最少的次数和最优的计算顺序?
(A1A2...Ai)(Ai+1....An)其中1<=i<=n,找出其中最少的乘法次数就是A1....An的最优解。对于A1...Ai;Ai+1...An可以采用同样的算法找出最优的乘法次数。现在取矩阵序列的任一段进行分析:Ai....Aj,m[i][j]是其乘法所需要的最少乘法次数,(Ai...Ak)(Ak+1...Aj)其中i<=k<j,左边所用的乘法次数m[i][k]、右边所要的乘法次数m[k+1][j]。
所以m[i][j]=min{ m[i][k]+m[k+1][j]+c[i-1]c[k]c[j] }其中c[i]表示第i个矩阵的列数。当i=1,j=n就找到了整体矩阵相乘的最少次数。
dynamic.h
dynamic.cpp
Algorithm-dynamic1.cpp
比如:斐波那契数是一个常见的递归计算过程,采用递归算法程序效率非常低。递归算法是模仿递归过程的,计算F(n),存在一个对F(n-1)和F(n-2)的调用,求解F(n-1),要对F(n-2)、F(n-3)的调用,存在2次对F(n-2)的计算、F(n-3)计算3次,F(n-4)计算5次等等。随着n的增大,对底层的计算次数呈现指数增长。其实计算F(n)时只要F(n-1)和F(n-2),因此只要记录最近计算的两个斐波那契数就OK。动态规划的思想就是把底层计算的结果存储以供上一层计算时使用,这样就避免了重复的计算。
下面介绍动态规划如何用于解决矩阵乘法的顺序安排问题:
例子:4个矩阵A、B、C、D,大小分别为:50*10、10*40、40*30、30*5,乘积ABCD可以任意加括号在计算其值。不同的计算顺序乘法次数不一样。
(A((BC)D)):16000次乘法;(A(B(CD))):10500次乘法;((AB)(CD)):36000次乘法;(((AB)C)D):87500次乘法;((A(BC))D):34500次乘法。
找到最优的计算次序可以有效的降低计算量。
给定矩阵A1,A2,...An,如何找到其计算最少的次数和最优的计算顺序?
(A1A2...Ai)(Ai+1....An)其中1<=i<=n,找出其中最少的乘法次数就是A1....An的最优解。对于A1...Ai;Ai+1...An可以采用同样的算法找出最优的乘法次数。现在取矩阵序列的任一段进行分析:Ai....Aj,m[i][j]是其乘法所需要的最少乘法次数,(Ai...Ak)(Ak+1...Aj)其中i<=k<j,左边所用的乘法次数m[i][k]、右边所要的乘法次数m[k+1][j]。
所以m[i][j]=min{ m[i][k]+m[k+1][j]+c[i-1]c[k]c[j] }其中c[i]表示第i个矩阵的列数。当i=1,j=n就找到了整体矩阵相乘的最少次数。
dynamic.h
#pragma once #include<iostream> #include<vector> using namespace std; class matrix { public: void insert(int num,string s);//输入第一个矩阵的行数、和所有矩阵的列数。 void optmatrix(); //选择最优的计算方法:最少的计算次数和计算顺序 void show(); //输出最小的计算次数和计算顺序 void track(int i,int j);//寻找最优计算次序 private: vector<int> c; //保存输入矩阵第一个行数和所有矩阵的列数 vector<string> str; vector<vector<long> >m;//保存计算最少次数 vector<vector<int> >lastchange;//矩阵乘法结合划分位置 };
dynamic.cpp
#include "stdafx.h" #include"dynamic.h" #include<iostream> #include<vector> #include<limits> using namespace std; void matrix::insert(int num,string s)//mun数组的列数,s对应数组的名称 { c.push_back(num); str.push_back(s); } void matrix::optmatrix() { int size=c.size()-1; m.resize(c.size()); lastchange.resize(c.size()); for(int i=0;i<c.size();i++) { m[i].resize(c.size()); lastchange[i].resize(c.size()); } for(int i=0;i<c.size();i++)//m[i,j]表示i位置到j位置矩阵乘积最少次数 { m[i][i]=0; lastchange[i][i]=0; } /* 下面求解矩阵相乘乘法次数最少,是采用由底向上计算,先求解所有相邻的2个矩阵最少的乘法次数,然后再求解3个相邻的矩阵乘法次数,依次类推。 直到所有矩阵都在一起相乘的最少乘法次数。 例如:A1 A2 A3 A4 ;先求解:A1*A2、A2*A3、A3*A4,的乘法次数。然后再求:A1*A2*A3、A2*A3*A4最少的乘法次数,计算三个相乘时要用到前面2个相乘 的结果。最后求解:A1*A2*A3*A4,其求解用到前面的结果 */ for(int k=1;k<size;k++)//k=right-left for(int left=1;left<=size-k;left++) { int right=left+k; m[left][right]=numeric_limits<long>::max(); for(int i=left;i<right;i++) { long temp=m[left][i]+m[i+1][right]+c[left-1]*c[i]*c[right]; if(temp<m[left][right]) { m[left][right]=temp; lastchange[left][right]=i; } } } } void matrix::show() { optmatrix(); int n=c.size()-1; vector<string>::iterator it=str.begin(); cout<<"最小的运算次数为:"<<m[1] <<endl; cout<<"计算顺序:"<<endl; track(1,n); cout<<endl; } void matrix::track(int i,int j) { if(i==j) { cout<<str[i]; return; } else { cout<<"("; track(i,lastchange[i][j]); track(lastchange[i][j]+1,j); cout<<")"; }}
Algorithm-dynamic1.cpp
//动态规划实现矩阵乘法的顺序安排 #include "stdafx.h" #include"dynamic.h" #include<iostream> #include<vector> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { matrix m; m.insert(50," ");//第一个矩阵的行数 m.insert(10,"A");//10列数,A矩阵的名 m.insert(40,"B"); m.insert(30,"C"); m.insert(5,"D"); m.show(); return 0; }
相关文章推荐
- 【转】矩阵和向量的乘法顺序
- 矩阵和向量的乘法顺序
- 动态规划算法之矩阵链式乘法
- 第25章:每对顶点间的最短路径—基于矩阵乘法的动态规划算法
- 动态规划算法之矩阵链乘法
- [zt]矩阵和向量的乘法顺序
- 数据结构26:矩阵乘法(行逻辑链接的顺序表),矩阵转置矩阵加法
- 动态规划--矩阵连乘的最优乘法顺序
- 矩阵和向量的乘法顺序
- 矩阵链乘法确定矩阵的最佳计算顺序
- 矩阵的乘法
- 写的一个小的矩阵乘法
- 实现两个N*N矩阵的乘法,矩阵由一维数组表示
- 卷积操作中的矩阵乘法(gemm)—— 为什么矩阵乘法是深度学习的核心所在
- [数论][二项式定理][矩阵乘法] BZOJ 3328: PYXFIB
- POJ3213(矩阵乘法)
- 【[Offer收割]编程练习赛13 D】骑士游历(矩阵模板,乘法,加法,乘方)
- bzoj2396: 神奇的矩阵(矩阵乘法+随机化)
- 【整体二分+二维树状数组】BZOJ2738 矩阵乘法
- Codevs 1070 普通递归关系(矩阵乘法)