动态规划 矩阵连乘问题
2016-12-04 15:12
633 查看
什么是动态规划
看到把原始问题划分成一系列子问题,我们很容易想到分治算法,但是对于分治算法,很可能会遇到子问题被重复使用
就像下面这个矩阵连乘,分解为子问题就会出现三个重复子问题,用分治算法时,就会重复计算相同的子问题,使程序效率变得低下
所以,这就是动态规划的用武之地:对于一个问题,可分为多个相关子问题,子问题的解被重复使用
矩阵连乘问题
对于矩阵连乘,假设A为10 * 100 的矩阵, B为100 * 5 的矩阵,C为5 * 50的矩阵,那么有两种情况:1、(A * B) * C 一共要乘 10 * 100 * 5 + 10 * 5 * 50 = 7500次
2、A * (B * C) 一共要乘 100 * 5 * 50 + 10 * 100 * 50 = 750000次
可以看到,不同顺序的相乘,就会有不同的时间复杂度,动态规划就是要来求一个最优解。
把这个括号的位置设为k,那么(A * B) * C 的k值就为2,表示A 和 B的矩阵先乘;A * (B * C) 的 k 值为 1, 表示B 和 C的矩阵相乘。
那么我们要做的就是如何确定这个k值,使得矩阵相乘具有最优解。
m[i, j]是指矩阵 i 到 矩阵 j 相乘的最小乘法数
p之间相乘是指拆分的矩阵之间的相乘
对于A * B * C:
m[1,3] = m[1,1] + m[2, 3] + p0 * p1 * p3 的意思是 A * (B * C)
m[1,3] = m[1,2] + m[3, 3] + p0 * p2 * p3 的意思是 (A * B) * C
也可以用这个图来理解
例如求m[1, 3] 就是 求 m[1, 1] 和 m[2, 3] 或者 求 m[1, 2] 和 m[3, 3。
代码实现
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define SIZE 100 #define INF 999999999 int p[SIZE]; int m[SIZE][SIZE]; //存放矩阵链计算的最优值,d[i][j]为第i个矩阵到第j个矩阵的矩阵链的最优值 int Best_DP(int n) { memset(m, 0, sizeof(m)); int len; for (len = 1; len <= n; len++) { int i, j, k; for (i = 1, j = i+len; j <= n; i++, j++) { int min = INF; for (k = i; k < j; k++) { int count = m[i][k] + m[k+1][j] + p[i-1] * p[k] * p[j]; if (count < min) { min = count; } } m[i][j] = min; } } return m[1] ; } int main(void) { int n; while (scanf("%d", &n) != EOF) { int i; for (i = 0; i <= n; i++) { scanf("%d", &p[i]); } printf("%d\n", Best_DP(n)); } return 0; }
这里需要注意的是:
n是指相乘的矩阵数目
p用来存放各矩阵的信息: 用p[i - 1] 和 p[i]来表示第i个矩阵的行和列,例如 A为10 * 100 的矩阵, B为100 * 5 的矩阵,C为5 * 50的矩阵,则p[0] = 10 , p[1] = 100, p[2] = 5 , p[3] = 50
m[i, j]用来表示i 到 j矩阵相乘的最优解
时间复杂性和空间复杂性
相关文章推荐
- 动态规划之矩阵连乘问题
- 【动态规划】矩阵连乘问题
- 动态规划——矩阵连乘问题
- 【编程素质】算法-矩阵连乘问题(枚举法、备忘录法、动态规划)
- 矩阵连乘问题(动态规划)
- 第3章 动态规划 矩阵连乘问题
- 动态规划 - 矩阵连乘问题(笔记)
- 动态规划 矩阵连乘问题
- 动态规划--矩阵连乘问题
- 动态规划——矩阵连乘的问题
- 动态规划——矩阵连乘的问题
- 矩阵连乘问题(动态规划)
- 第3章 动态规划 矩阵连乘问题
- 算法[动态规划]-矩阵连乘问题
- 动态规划——矩阵连乘的问题
- 0010算法笔记——【动态规划】矩阵连乘问题
- 动态规划之矩阵连乘问题
- 动态规划求解矩阵连乘问题Java实现
- 0010算法笔记——【动态规划】矩阵连乘问题
- 动态规划最优矩阵连乘问题