动态规划之矩阵连乘
2015-09-24 22:49
169 查看
题目:n个矩阵连乘,求最少的乘法运算次数以及结合方式
假设矩阵A为r1*r2,矩阵B为r2*r3,所以M=A*B=r1*r2*r3。当有多个矩阵相乘的时候,矩阵以不同的方式结合的时候其运算次数是不同的。
例如:M=M1 * M2 * M3 * M4
[5*20] [20*50] [50*1] [1*100]
((M1*M2)*M3)*M4=5000+250+500=5750
而M1*(M2*(M3*M4))=5000+100000+10000=115000
如果按照(M1*(M2*M3)*M4)=1000+100+500=1600
上面的例子说明根据不同的结合顺序,运算的次数是不同的。现在我们就是要求通过哪种顺序所进行的乘法运算次数最少,并且求出运算最少的次数是多少。
算法思想:
记Mi*Mi+1*Mi+2*...*Mj为mij,矩阵的大小为:M1为r1*r2,M2为r2*r3,M3为r3*r3,M4为r4*r5。r1,r2,r3,r4,r5分别为5,20,50,1,100.
(1)首先计算矩阵相乘个数为2的3种情况。
m12=M1*M2=r1*r2*r3=5000,m23=r2*rr*r4,m34=r3*r4*r5=1000,m34=5000
(2)计算相乘矩阵个数为3的2种情况
m13=M1*M2*M3,目标是求出m13的乘法运算次数最小值。m13=min{M1*m23+r1*r2*r4,m12*M3+r1*r3*r4}=min{1100,5250}=m12*M3+r1*r3*r4=1100
同理 m24=M2*M3*M4=min{M2*m34+r2*r3*r,m23*M4+r2*r4*r5}=min{10500,3000}=3000;
(3)最后计算相乘矩阵个数为4的最终结果:
m14=min(m13*M4+r1*r4*r5,m12*m34+r1*r3*r4,M1*m24+r1*r2*r5)={3000+10000 ,5000+5000,+25000,1100+500}=1600
算法如下
com适用于保存矩阵的结合方式的com[i][j]=k,表示的是mik*mkj的时候进行乘法的次数最少
递归调用的过程如下:
1-2,2-3,3-4等子问题都被递归调用了2次,子问题存在重复。可以采用备忘录方法解决该问题,设置一个全局变量m[i][j[,存储已经计算过的course(i,j)的值,下次调用的时候直接使用。
假设矩阵A为r1*r2,矩阵B为r2*r3,所以M=A*B=r1*r2*r3。当有多个矩阵相乘的时候,矩阵以不同的方式结合的时候其运算次数是不同的。
例如:M=M1 * M2 * M3 * M4
[5*20] [20*50] [50*1] [1*100]
((M1*M2)*M3)*M4=5000+250+500=5750
而M1*(M2*(M3*M4))=5000+100000+10000=115000
如果按照(M1*(M2*M3)*M4)=1000+100+500=1600
上面的例子说明根据不同的结合顺序,运算的次数是不同的。现在我们就是要求通过哪种顺序所进行的乘法运算次数最少,并且求出运算最少的次数是多少。
算法思想:
记Mi*Mi+1*Mi+2*...*Mj为mij,矩阵的大小为:M1为r1*r2,M2为r2*r3,M3为r3*r3,M4为r4*r5。r1,r2,r3,r4,r5分别为5,20,50,1,100.
(1)首先计算矩阵相乘个数为2的3种情况。
m12=M1*M2=r1*r2*r3=5000,m23=r2*rr*r4,m34=r3*r4*r5=1000,m34=5000
(2)计算相乘矩阵个数为3的2种情况
m13=M1*M2*M3,目标是求出m13的乘法运算次数最小值。m13=min{M1*m23+r1*r2*r4,m12*M3+r1*r3*r4}=min{1100,5250}=m12*M3+r1*r3*r4=1100
同理 m24=M2*M3*M4=min{M2*m34+r2*r3*r,m23*M4+r2*r4*r5}=min{10500,3000}=3000;
(3)最后计算相乘矩阵个数为4的最终结果:
m14=min(m13*M4+r1*r4*r5,m12*m34+r1*r3*r4,M1*m24+r1*r2*r5)={3000+10000 ,5000+5000,+25000,1100+500}=1600
算法如下
#include <iostream> using namespace std; int r[100],com[100][100]; int course(int i,int j) { int u,t; if(i==j) return 0; if(i==j-1) { com[i][j]=i; return r[i]*r[i+1]*r[i+2]; } else { u=course(i,i)+course(i+1,j)+r[i]*r[i+1]*r[j+1]; com[i][j]=i; for(int k=i;k<j;k++) { t=course(i,k)+course(k+1,j)+r[i]*r[k+1]*r[j+1]; if(t<u) { u=t; com[i][j]=k; } } return u; } } int main() { int n; printf("input n:"); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&r[i]); printf("min=%d\n",course(1,n-1)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) printf("%d ",com[i][j]); printf("\n"); } return 0; }
com适用于保存矩阵的结合方式的com[i][j]=k,表示的是mik*mkj的时候进行乘法的次数最少
递归调用的过程如下:
1-2,2-3,3-4等子问题都被递归调用了2次,子问题存在重复。可以采用备忘录方法解决该问题,设置一个全局变量m[i][j[,存储已经计算过的course(i,j)的值,下次调用的时候直接使用。
相关文章推荐
- C#面试 笔试题 六
- 安卓旅途之——开发数独(一)
- RAID技术介绍和总结
- jquery和css自定义video播放控件
- <转载>DIV+CSS position定位方法总结
- [OpenCV] Write & Read files
- [OpenCV] Write & Read files
- 使用VS下载C#API(.NET Framework 类库)
- <转载>如果在浏览器网页标题栏左侧加自定义小图标
- <转载>使CSS文字图片div元素居中方法之水平居中的几个方法
- python 文件的读写与查找
- 马哥linux+python——2015年9月13日课程作业
- Linux终端:
- SEM 关键词的选择
- <转载>div+css布局教程之div+css常见布局结构定义
- Linux的系统层次
- tcpdump命令
- XHTML5 ----- 实现多媒体播放
- 杭电acm--2075
- <转载>Div+Css布局教程(-)CSS必备知识