这是《算法导论》动态规划中的一个问题。问题简述如下:我们在求解矩阵相乘时通常会有一个最优括号方案来对矩阵进行顺序相乘,这样会减少大量的计算时间。

  我们知道矩阵A、B相乘,只能是当矩阵A的列数等于矩阵B的行数时才能进行相乘,且假设A·B = C,A为p×q规模的矩阵,B为q×r的矩阵,则乘积C的规模为p×r的矩阵。计算A·B所需的时间由乘法次数决定,即pqr。

  例如:有三个矩阵的规模分别为:A = 10×100,B = 100×5,C = 5×50。如果按顺序(AB)C计算,则需要10×100×5 + 10×5×50 = 7500次乘法,如果按顺序A(BC)计算,则需要100×5×50 + 10×100×50 = 75000次乘法...所以,按第一种顺序计算矩阵链乘积要比第二种快非常多。

  矩阵链乘法问题可描述如下:给定n个矩阵的链<A1,A2,...,An>,矩阵Ai的规模为pi-1×pi(1 ≤ i ≤ n),求完全括号化方案,使得计算乘积A1A2...An所需标量乘法次数最少。

  分析问题描述可知道,我们假设在矩阵链乘中找到一个合适的切割点进行括号化,可得到问题的最优括号方案,然后对切割点的两边的子问题用相同的方法独立求解,不断进行下去,则最终将得到原问题的最优解。这就是该问题的最优子结构。

  构造递归公式:令m[i][j] 表示计算矩阵Ai...j所需标量乘法次数的最小值,那么,原问题的最优解 —— 计算A1...n所需的最低代价就是m[1][n]。

  对于i = j 时,矩阵链只包含唯一的矩阵 Ai...i = Ai ,不需要做任何标量乘法运算。若 i < j,利用最优子结构来计算m[i][j]。如前面假设Ai,Ai + 1,...,Aj的最优括号化方案的分割点在矩阵的Ak和Ak + 1之间,其中i ≤ k < j。那么,m[i][j]就等于计算Ai...k和Ak + 1...j的代价加上两者相乘的代价的最小值。由于矩阵Ai的大小为pi×pi+1,易知Ak+1...j相乘的代价为pi·pk+1·pj+1次标量乘法运算。因此,得到:

m[i][j] = m[i][k] + m[k + 1][j] + p[i]·p[k + 1]·p[j + 1]

  由于k值取法只有 j - i 种可能的取值,即k = i, i + 1, ..., j。检查所有可能的情况,找到最优,因此递归公式变为:

           (    0,                 i = j;
m[i][j] = {
( min(m[i][k] + m[k + 1][j] + p[i]·p[k + 1]·p[j + 1]), i < j.

  O(n^3)迭代解法:

#include <iostream>
#include <vector> class Solution {
public:
std::vector<std::vector<int> > MatrixChainOrder(std::vector<int>& p)
{
const int n = p.size() - 1;
std::vector<std::vector<int> > m(n, std::vector<int> (n)); for(int i = 0; i < n; i++)
{
m[i][i] = 0;
}
for(int l = 1; l < n; l++)
{
for(int i = 0; i < n - l; i++)
{
int j = i + l;
m[i][j] = INT_MAX - 1;
for(int k = i; k < j; k++)
{
int q = m[i][k] + m[k + 1][j] + p[i]*p[k + 1]*p[j + 1];
if(q < m[i][j])
{
m[i][j] = q;
}
}
}
} return m;
}
}; int main()
{
std::vector<int> p{30, 35, 15, 5, 10, 20, 25};
Solution solve;
std::vector<std::vector<int> > res = solve.MatrixChainOrder(p); for(int i = res.size() - 1; i >= 0; i--)
{
for(int j = 0; j <= i; j++)
std::cout << res[j][i] << ' ';
std::cout << std::endl;
} return 0;
}

  递归版感觉有点问题...所以再研究一段时间。

  参考资料:以上皆为《算法导论》 — 动态规划原文

  

MCM(矩阵链乘法)的更多相关文章

  1. POJ1260 Pearls(dp,矩阵链乘法)

    题目链接. 题目大意: 给定一个n,和两个序列a[i], p[i]. a[i] 表示需要购买 i品质 的数量,p[i] i 等级的价格. 1.每个品质都会有不同的价格,价格依据品质上升而上升 2.买一 ...

  2. Algorithm --> 矩阵链乘法

    动态规划--矩阵链乘法 1.矩阵乘法       Note:只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×r的矩阵A左乘一个r×n的矩阵B,会得到一个m×n的矩阵C. #include ...

  3. CODEVS 3546 矩阵链乘法

    http://codevs.cn/problem/3546/ 题目 给定有n个要相乘的矩阵构成的序列(链)<A1,A2,A3,.......,An>,要计算乘积A1A2.....An.一组 ...

  4. 【动态规划】XMU 1029 矩阵链乘法

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1029 题目大意: 题同乘法难题.给n+1个数,头尾不能动,中间的数可取出,取出时代价是 ...

  5. 【CODEVS】3546 矩阵链乘法

    [算法]区间DP [题解] 注意先输出右括号后输出左括号. f[i][i+x-1]=min(f[i][i+x-1],f[i][j]+f[j+1][i+x-1]+p[i]*p[j+1]*p[i+x]) ...

  6. 51 Nod 1013 3的幂的和 矩阵链乘法||逆元+快速幂

    这道题我写了两种写法 一种利用逆元 a/b%mod=a*c%mod; (c是b的逆元)易得2的逆元就是5~~~04: 一种是矩阵快速幂 利用递推式得出结论 #include<cstdio> ...

  7. 【UVa-442】矩阵链乘——简单栈练习

    题目描述: 输入n个矩阵的维度和一些矩阵链乘表达式,输出乘法的次数.如果乘法无法进行,输出error. Sample Input 9 A 50 10 B 10 20 C 20 5 D 30 35 E ...

  8. COJ 0016 20603矩阵链乘

    传送门:http://oj.cnuschool.org.cn/oj/home/solution.htm?solutionID=35454 20603矩阵链乘 难度级别:B: 运行时间限制:1000ms ...

  9. (最大矩阵链乘)Matrix-chain product

    Matrix-chain product. The following are some instances. a)       <3, 5, 2, 1,10> b)       < ...

随机推荐

  1. Java进阶学习(2)之对象交互(下)

    访问属性 封闭的访问属性 private等访问权限控制是对类的,这意味着同一类的不同对象可以互相访问其成员 这是从代码层面去考虑的,意味着不同类文件 开放的访问属性 一个类文件就是一个编译单元 pub ...

  2. NOIP-- 模拟-----机器

    机器翻译 题目描述 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先 ...

  3. 使用Eclipse工具开发Servlet(新建web项目->创建Servlet->部署和访问Servlet)

    在Eclipse工具栏中的[File]->[New]->[Other],打开如下菜单栏,选择Dynamic Web Project 点击下一步,如下图所示: 这里Dynamic web m ...

  4. JS-try/catch方法判断字符串是否为json格式

    定义: try/catch 语句用于处理代码中可能出现的错误信息,出现异常会导致程序崩溃,而try/catch 则可以保证程序的正常运行. try { //执行代码 不报错则 正常执行 不会进入下面的 ...

  5. python函数1_参数,返回值和嵌套

    函数 将重复的代码,封装到函数,只要使用直接找函数 函数可以增强代码的模块化和提高代码的重复利用率 函数的定义和调用 格式 def 函数名([参数,参数...]): 函数体 定义函数 import r ...

  6. 「JSOI2012」玄武密码

    「JSOI2012」玄武密码 传送门 题目是要求多个串在母串上的最长匹配长度. 考虑 \(\text{AC}\) 自动机,我们建出 \(\text{Trie}\) 图然后用母串来在上面跑. 每一个能匹 ...

  7. Vue ElementUI Tree组件 回显问题(设置选择父级时会全选所有的子级,有此业务场景是不适合的)

    业务场景下有这样的问题 业务需求需要保存前端 半选节点 解决方案 let checked = this.$refs.menuTree.getCheckedKeys(); //此方法获取半选节点 let ...

  8. MAC系统 -java开发环境搭建

    MAC - java开发环境搭建 软件: jdk Intellij IDEA:java开发工具 maven:jar包管理 git :源码管理 sourceTree :源码管理GUI客户端 Studio ...

  9. C语言-数组与指针 字符与字符串

    1 字符与字符串:char c='a'而不能写出char c="a" //字符变量用单引号'',而字符串用双引号. 2 字符数组与字符指针的初始化: char s[10]={0}, ...

  10. 字符串操作函数:JSON.parse()与JSON.stringify()的区别,字符串转数组 str.split(','),数组转字符串String(),以及对象拼接合并Object.assign(),数组拼接合并concat()

    1.JSON.parse()  把字符串转化为 json 对象 例如 arr={ , "site":"www.runoob.com" } var obj = J ...