【编程素质】算法-矩阵连乘问题(枚举法、备忘录法、动态规划)
来源:互联网 发布:卖淘宝号的网站 编辑:程序博客网 时间:2024/06/04 18:49
1,问题
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。
2,枚举法(穷举搜索法)
枚举所有加括号的方式。
对于n个矩阵的连乘积,设其不同的计算次序为P(n)。每个问题可分解为两个子问题:(A1…Ak)(Ak+1…An)可以得到关于P(n)的递推式如下:
以上递推关系说明,P(n)是随n的增长呈指数增长的。因此,穷举法不是一个多项式时间复杂度算法。
3,备忘录算法
1)概念
备忘录方法是动态规划算法的变形。用表格保存子问题答案,避免重复计算。
与动态规划不同的是:备忘录方法的递归是自顶向下的,而动态规划是自底向上的。
备忘录方法为每个问题建立一个记录项(如赋初值为0),初始化时,该记录项存入一个特殊值,表示该问题尚未求解。
2)分析
上图为枚举过程,其中黑色方格为重复计算。备忘录就是用来保存计算结果,在每次计算前查表,如果计算过,则直接取值,避免重复计算。
4,动态递归算法
以矩阵链ABCD为例:
矩阵链长度为n。
n=1时,分别计算A、B、C、D最优值。
n=2时,分别计算AB、BC、CD最优值。
n=3时,分别计算ABC、BCD最优值。
n=4时,分别计算ABCD的最优值。
令:
k:为矩阵链断开的位置
d:数组存放矩阵链计算的最优值,d[i][j]是以第i个矩阵为首,第j个矩阵为尾的矩阵链的最优值,i > 0
m:存放矩阵链行列信息的数组,m[i-1]和m[i]分别为第i个矩阵的行和列(i = 1、2、3…)
5,代码
package MatrixMultiply;public class Main { public static void main(String[] args) { /** * 6个矩阵连乘 * A1:30*35 * A2:35*15 * A3:15*5 * A4:5*10 */ final int L = 7; int[] p={30,35,15,5,10}; int N = MatrixMultiply.Best_Enum(p, 1, 4); System.out.println("Best_Enum矩阵计算最少次数:" + N); N = MatrixMultiply.Best_Memo(p, 1, 4); System.out.println("Best_Memo矩阵计算最少次数:" + N); N = MatrixMultiply.Best_DP(p, p.length); System.out.println("Best_DP矩阵计算最少次数:" + N); }}
package MatrixMultiply;public class MatrixMultiply { private final static int MAX_INT = 99999999;// 表示无穷大 private final static int SIZE = 10;// 数组大小 /** * 枚举法(递归算法) * * @param m * 矩阵 m数组内存放矩阵链的行列信息 m[i-1]和m[i]分别为第i个矩阵的行和列(i = 1、2、3...) * @param left * 左括号索引 * @param right * 右括号索引 * @return */ public static int Best_Enum(int m[], int left, int right) { // 只有一个矩阵时,返回计算次数0 if (left == right) { return 0; } int min = MAX_INT; // 无穷大 int i; // 括号依次加在第1、2、3...n-1个矩阵后面 for (i = left; i < right; i++) { // 计算出这种完全加括号方式的计算次数 int count = Best_Enum(m, left, i) + Best_Enum(m, i + 1, right); count += m[left - 1] * m[i] * m[right]; // 选出最小的 if (count < min) { min = count; } } return min; } public static int[][] memo = new int[SIZE][SIZE]; /** * 备忘录法 * * @param m * m数组内存放矩阵链的行列信息 m[i-1]和m[i]分别为第i个矩阵的行和列(i = 1、2、3...) * @param left * @param right * @return */ public static int Best_Memo(int m[], int left, int right) { // 只有一个矩阵时,返回计算次数0 if (left == right) { return 0; } int min = MAX_INT; int i; // 括号依次加在第1、2、3...n-1个矩阵后面 for (i = left; i < right; i++) { // 计算出这种完全加括号方式的计算次数 int count; if (memo[left][i] == 0) { memo[left][i] = Best_Memo(m, left, i); } count = memo[left][i]; if (memo[i + 1][right] == 0) { memo[i + 1][right] = Best_Memo(m, i + 1, right); } count += memo[i + 1][right]; count += m[left - 1] * m[i] * m[right]; // 选出最小的 if (count < min) { min = count; } } return min; } private static int[][] d = new int[SIZE][SIZE]; // 存放矩阵链计算的最优值,d[i][j]为第i个矩阵到第j个矩阵的矩阵链的最优值,i // > 0 /** * 动态规划算法 * * @param n * @return */ public static int Best_DP(int[] m, int n) { // 把d[i][i]置为0,1 <= i < n for (int i = 0; i < SIZE; i++) { java.util.Arrays.fill(d[i], 0); } int len; // 递归计算矩阵链的连乘最优值 // len = 1,代表矩阵链由两个矩阵构成 for (len = 1; len < n; len++) { int i, j, k; for (i = 1, j = i + len; j < n; i++, j++) { int min = MAX_INT; // 无穷大 for (k = i; k < j; k++) { int count = d[i][k] + d[k + 1][j] + m[i - 1] * m[k] * m[j]; if (count < min) { min = count; } } d[i][j] = min; } } return d[1][n - 1]; }}
阅读全文
0 0
- 【编程素质】算法-矩阵连乘问题(枚举法、备忘录法、动态规划)
- 算法[动态规划]-矩阵连乘问题
- 算法 矩阵连乘 递归+动态规划+备忘录
- 矩阵连乘问题的动态规划算法(java)
- 矩阵连乘问题(动态规划)
- 矩阵连乘的动态规划算法(包括递归的备忘录方法)
- 动态规划-3.1.3矩阵连乘问题之备忘录方法(自顶向下)
- 【计算机算法分析】动态规划法——矩阵连乘问题
- 动态规划经典算法之矩阵连乘问题源代码
- 动态规划算法——矩阵连乘问题
- 算法笔记——【动态规划】矩阵连乘问题
- 算法动态规划问题之矩阵连乘
- 算法笔记-010矩阵连乘问题----动态规划
- 矩阵连乘--动态规划算法
- 矩阵连乘的动态规划算法
- 矩阵连乘动态规划算法
- 3.1.2矩阵连乘问题之动态规划法(自底向上)
- 动态规划 - 矩阵连乘问题
- Hystrix 使用与分析
- ListBox设置AddString排序
- git help 用chrome打开
- 袁萌:高考恢复40年有感
- 关于spring+hibernate的FlushMode的记录
- 【编程素质】算法-矩阵连乘问题(枚举法、备忘录法、动态规划)
- 《Android源码设计模式解析与实战》读书笔记(二十)——适配器模式
- Linux网络编程【五】:TCP协议高性能服务器(http)模型之I/O多路转接select
- Spring AOP aspectjweaver.jar包
- 读写锁
- 使用直方图及其部分空间特性的模糊对比
- Git查看、删除、重命名远程分支和tag
- bat文件命令行去除变量的空格
- Kotlin 双冒号 :: 使用