矩阵链乘法
来源:互联网 发布:温州市网络问政平台 编辑:程序博客网 时间:2024/06/05 16:35
矩阵链乘法
•给定一个由n个矩阵构成矩阵序列(链)<A1, A2, ..., An>
,要将它们相乘(假定它们按此序列是乘法相容的:Ai是pi-1×pi矩阵,而Ai+1是pi×pi+1矩阵),计算积:
A1A2 ... An
•只要对此序列加上括号,确定运算顺序,就可以算得它们的积。矩阵链的积称为是完全加括号的,若它或是单一的矩阵,或是两个完全加括号的矩阵子链之积,并用一对括号括起来。
1.问题的理解与描述
•输入:数组<p0, p1, …, pn>
,其中pi-1和pi分别是矩阵Ai的行数和列数,i=1, 2, …, n。
•输出:计算积A1A2 … An的最优完全加括号形式。
2.最优子结构
•假定Ai Ai+1… Aj的最优完全加括号在Ak及Ak+1之间分裂。则该加括号的“前缀”子链Ai Ai+1… Ak在Ai Ai+1… A j的此最优加括号中的完全加括号必为Ai Ai+1… Ak的最优加括号。
•设m[i, j]为计算矩阵所需的最少标量乘法次数,根据上面的最优子结构的讨论,我们有:
┌ 0 如果i = jm[i,j] = │ └ min(i≤k<j) {m[i,k] + m[k+1,j] + Ai.row*Ak.col*Aj.col} 如果i < j
3.算法的伪代码描述
MATRIX-CHAIN-ORDER(p)n ← length[p] - 1for i ← 1 to n do m[i, i] ← 0for l ← 2 to n //l 是矩阵链的长度 do for i ← 1 to n - l + 1 do j ← i + l - 1 m[i, j] ← ∞ for k ← i to j - 1 do q ← m[i, k] + m[k + 1, j] + pi-1 pkpj if q < m[i, j] then m[i, j] ← q s[i, j] ← kreturn m and s
- 代码实现
4.1 C语言版
pair.h file
#ifndef _PAIR_H#define _PAIR_H#ifdef __cplusplusextern "C" //告诉编译器{ }内部是用C写成的文件,请用C的方式来连接他们{#endif typedef struct { void* first; void* second; }pair; pair make_pair(void*f, void*d); pair matrixChainOrder(int *p, int n); void printOptimalParens(int *s, int i, int j, int n);#ifdef __cplusplus}#endif#endif
pair.c file
#include <stdlib.h>#include <stdio.h>#include<limits.h>#include "pair.h"pair make_pair(void*f, void*d){ pair p = { f, d }; return p;}pair matrixChainOrder(int *p, int n){ int i, l, j, k, q; int *m = (int*)malloc((n + 1)*(n + 1)*sizeof(int));//m 存储最小标量乘法次数 int *s = (int*)malloc((n + 1)*(n + 1)*sizeof(int));//s:存储最优解表格 for (i = 0; i <= n; i++) m[i*(n + 1) + i] = 0;//m[i][i]=0 for (l = 2; l <= n ; l++)//l 为子矩阵链的长度 for (i = 1; i <= n - l + 1;i++) { j = i + l - 1; m[i*(n + 1) + j] = INT_MAX;//m[i,j]=∞ for (k = i; k <= j - 1;k++) { q = m[i*(n + 1) + k] + m[(k + 1)*(n + 1) + j] + p[i - 1] * p[k] * p[j]; if (q<m[i*(n+1)+j]) { m[i*(n + 1) + j] = q; s[i*(n + 1) + j] = k; } } } return make_pair(m, s);}void printOptimalParens(int *s, int i, int j, int n){ if (i == j) printf("A%d",i); else { printf("("); printOptimalParens(s, i, s[i*(n + 1) + j],n); printOptimalParens(s, s[i*(n + 1) + j] + 1, j,n); printf(")"); }}
main.c file
#include <stdio.h>#include <stdlib.h>#include "pair.h"int main(int argc, char ** argv){ int p[] = { 30, 35, 15, 5, 10, 20, 25 }; int *s, *m; pair r = matrixChainOrder(p, 6); m = (int*)r.first; s = (int*)r.second; printOptimalParens(s, 1, 6, 6); printf("\n the min muilty times is: %d \n", m[13]); free(s); free(m); system("pause"); return (EXIT_SUCCESS);}
4.2 C++版
matrixchain.cpp fiel
#include "stdafx.h"#include "matrixchain.h"#include <climits>pair<int*, int*>matrixChainOrder(int*p, int n){ long i, l, j, k, q; int *m = new int[(n + 1)*(n + 1)]; int *s = new int[(n + 1)*(n + 1)]; for (i = 1; i <= n; i++) m[i*(n + 1) + i] = 0;//m[i,i]=0 for (l = 2; l <= n; l++) for (i = 1; i <= n - l + 1;i++) { j = i + l - 1; m[i*(n + 1) + j] = INT_MAX; for (k = i; k <= j - 1;k++) { q = m[i*(n + 1) + k] + m[(k + 1)*(n + 1) + j] + p[i - 1] * p[k] * p[j]; if (q<m[i*(n+1)+j]) { m[i*(n + 1) + j] = q; s[i*(n + 1) + j] = k; } } } return make_pair(m, s);}void printOptimalParens(int *s, int i, int j, int n){ if (i == j) cout << 'A' << i; else { cout << '('; printOptimalParens(s, i, s[i*(n + 1) + j], n); printOptimalParens(s, s[i*(n + 1) + j] + 1, j, n); cout << ')'; }}
matrixchain.h fiel
#ifndef _MATRIXCHAIN_H#define _MATRIXCHAIN_H#include <iostream>using namespace std;pair<int*, int*> matrixChainOrder(int*p, int n);void printOptimalParens(int *s, int i, int j, int n);#endif
main.cpp file
#include "stdafx.h"#include "matrixchain.h"int _tmain(int argc, _TCHAR* argv[]){ int p[] = { 30, 35, 15, 5, 10, 20, 25 }; int *s, *m; pair<int*,int*> r = matrixChainOrder(p, 6); m = r.first; s = r.second; printOptimalParens(s, 1, 6, 6); cout << endl << m[13] << endl; delete[]s; delete[]m; system("pause"); return 0;}
- 运行结果:
0 0
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 15.2 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 【DP】矩阵链乘法
- 矩阵链乘法
- 矩阵链乘法
- 链矩阵乘法
- Java的深拷贝和浅拷贝(转载)
- Windows CE: Prefetch Aborts, why they are difficult to locate
- 【开源框架】Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发,欢迎各位...
- dhcpv6 server test env building
- Android searchView和listview实现搜索
- 矩阵链乘法
- Apache配置禁止访问某些文件或目录
- linux用curl命令测试Post请求
- 程序员总结:帮助你早些明白一些道理
- 正则表达式 多个手机号之间使用英文逗号分隔
- Hadoop中Namenode无法启动
- Java中==和equals()的区别
- Java多线程的用法详解
- facade模式 界面统一模式