最优矩阵链乘

一.问题描述  

  与分治法不同的是动归的子问题间不是相互独立的,前一个往往为后一个提供信息。 

  看下面一个例子,计算三个矩阵连乘{A1,A2,A3};维数分别为10*100 , 100*5 , 5*50   按此顺序计算需要的次数((A1*A2)*A3):10X100X5+10X5X50=7500次   按此顺序计算需要的次数(A1*(A2*A3)):10X5X50+10X100X50=75000次  

  所以问题是:如何确定运算顺序,可以使计算量达到最小化。  

二.问题分析

  枚举显然不可,如果枚举的话,相当于一个“完全加括号问题”,次数为卡特兰数,卡特兰数指数增长,必然不行。  

  令m[i][j]表示第i个矩阵至第j个矩阵这段的最优解。 显然如果i=j,则m[i][j]这段中就一个矩阵,需要计算的次数为0;如果i>j,则m[i][j]=min{m[i][k]+m[k+1][j]+p[i-1]Xp[k]Xp[j]},其中k,在i与j之间游荡,所以i<=k<j ;

  注意的问题:计算顺序!!!   因为你要保证在计算m[i][j]查找m[i][k]和m[k+1][j]的时候,m[i][k]和m[k+1][j]已经计算出来了。

  下面采用记忆化搜索实现。

三.程序实现

  

 1 #include <iostream>
 2 using namespace std;
 3 const int N = 105;
 4 int c[N][N],s[N][N],p[N];
 5
 6  //根据s[][]记录的各个子段的最优解,将其输出
 7 void traceback(int i,int j)
 8 {
 9     if(i==j)
10         return ;
11     traceback(i,s[i][j]);
12     traceback(s[i][j]+1,j);
13     cout<<"Multiply A"<<i<<","<<s[i][j]<<"and A"<<s[i][j]+1<<","<<j<<endl;
14 }
15
16 int chain(int i,int j)
17 {
18     if(c[i][j]>0)
19         return c[i][j];
20     if(i==j)
21         return 0;
22     //初始化
23     int u=chain(i,i)+chain(i+1,j)+p[i-1]*p[i]*p[j];
24     s[i][j]=i;
25     for(int k=i+1;k<j;k++)
26     {
27         int t=chain(i,k)+chain(k+1,j)+p[i-1]*p[k]*p[j];
28         if(t<u)
29         {
30             u=t;
31             s[i][j]=k;
32         }
33
34
35     }
36     c[i][j]=u;
37     return u;
38 }
39 int main(int argc, char *argv[])
40 {
41     int n,i,j;
42     cin>>n;
43     for(i=0;i<=n;i++)
44     cin>>p[i];
45     cout<<chain(1,n)<<endl;
46     traceback(1,n);
47     //while(1);
48     return 0;
49 }  

 

时间: 2024-09-20 10:47:26

最优矩阵链乘的相关文章

【算法导论】动态规划之矩阵链乘法

       所谓矩阵链乘法是指当一些矩阵相乘时,如何加括号来改变乘法顺序从而来降低乘法次数.例如有三个矩阵连乘:A1*A2*A3,其维数分别为:10*100,100*5,5*50.如果按照((A1*A2)*A3)来计算的话,求(A1*A2)要10*100*5=5000次乘法,再乘以A3需要10*5*50=2500次乘法,因此总共需要7500次乘法.如果按照(A1*(A2*A3))来计算的话,求(A2*A3)要100*5*50=25000次乘法,再乘以A1需要10*100*50=50000次乘法

第十五章 动态规划——矩阵链乘法

前言:今天接着学习动态规划算法,学习如何用动态规划来分析解决矩阵链乘问题.首先回顾一下矩阵乘法运算法,并给出C++语言实现过程.然后采用动态规划算法分析矩阵链乘问题并给出C语言实现过程. 1.矩阵乘法       从定义可以看出:只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×r的矩阵A左乘一个r×n的矩阵B,会得到一个m×n的矩阵C.在计算机中,一个矩阵说穿了就是一个二维数组.一个m行r列的矩阵可以乘以一个r行n列的矩阵,得到的结果是一个m行n列的矩阵,其中的第i行第j列位置上的

寻博百优外链最好的方法 就是没有方法

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 文章的起因:最近看有人在A5发了新人寻找外链的方法,授人以鱼.我觉得我要改了这条鱼给他加三点水,授你以渔,让你自己也能抓鱼. 肯定有人要问我,没有方法那怎么找外链啊,你不是忽悠人吗?这位朋友,不要急躁,听我慢慢道来."且夫水之积也不厚,则其负大舟也无力.覆杯水于坳堂之上,则芥为之舟;置杯焉则胶,水浅而舟大也." – 引自庄

UVa 348 Optimal Array Multiplication Sequence:区间DP&amp;amp;矩阵链乘,MCM

348 - Optimal Array Multiplication Sequence Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=284 记忆化搜索:dp[a][b] = max(dp[a][b], dp[a][i] + dp[i + 1][b] + x

【算法导论】动态规划之最优二叉查找树

        如果我们想写一个单词查询的软件的话,我们的目的就是让查询的总时间最短,我们首先想到用之前的二叉查找树.我们可以用红黑树或者其它的平衡二叉树来保证每个单词的搜索时间.但是每个单词出现的频率一般不同,因此我们希望把频率较大的单词放在离根比较近的地方,频率较小的放在离叶子较近的地方.而且,我们所要查询的单词词库中没有,这也值得考虑.                        由上文可知,ki表示单词,di表示不能查到的情况.由上面的例子可知,一棵最优二叉树不一定是高度最小的树.我们

矩阵连乘的算法问题

写给自己的话: 有时候虽然一道题懂做了,但是发现写解题报告时,要清楚把自己的思路描述出来却挺难的.做解题报告 不仅可以巩固.梳理知识,还可以加深理解.现在我还做得很不好, 一定要坚持! 加油! 矩阵链乘问题: 例子: (下面第二个{P1应该是P2) void MatrixChain() { int i, j, k, t; for(i = 1; i <= n; i++) m[i][i] = 0; //对角线赋值为0,是因为1个矩阵需做0次相乘 for(r=2; r<=n; ++r){ for(i

博百优网站分析seo优化之链轮

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 最近那个单页的博百优排名一直都很不错,所以吸引了大家的眼球.各位站长纷纷的就对这个站做了分析,他的站就一个页面,外链也不是很多,怎么排名就这么好呢?外链环,专门baidu点击软件,可能最大的优点就在这里吧.这几天一直听大家说链轮的事,并且好多人都说这个站运用了这个seo方法,效果非常的好,所以这里说一些对链轮的一些信息. 链轮是创建一些web

Hackbuteer1的专栏Stay Hungry,Stay Foolish!

转自:http://blog.csdn.net/Hackbuteer1/rss/list [原]九度互动社区IT名企招聘上机考试热身赛 http://ac.jobdu.com/problem.php?id=1326     Waiting in Line   //简单模拟题 #include<iostream> #include<cstdio> using namespace std; #include<memory.h> int pt[1001],leave[1001

浅谈内部链接对网站影响的四个重点

现在的个人网站越来越多的人在做,并且很多人都把大部分精力集中在外链的这一块当中.其实外链只是一个小小的一部分,而内链却没有多少人去理会.事实上,如果你把内链做好了,那么我们自己的网站就会有更大的发展,不必一味着靠外链做推广,因为内链有着更好地优势.那么内链对网站有着怎样的意义呢?以下就是我在做网站的一些看法,希望对你们有帮助. 第一:建好内链,牢固地基. 有些人可能对内链不太了解,所谓内链就是在自己的网站内部进行的链接,或者说在同一个网站中浏览内容,而不会转到其他的网站中.从这里就可以知道如果我