矩阵连乘问题(动态规划算法)
动态规划算法思想简介:
将一个问题分解为多个子问题,这点和分治法类似,但是每个子问题不是独立的而是相互联系的,所以我们在求解每个子问题的时候可能需要重复计算到其他的子问题,所以我们将计算过的子问题的解放进一个表中,这样就能避免了重复计算带来的耗费,这就是动态规划的基本思想;
一般地,动态规划思想一般用来解最优化问题,主要分为以下四个步骤:
(1)找出最优解的性质,并刻画其结构特征;
(2)递归地定义最优值;
(3)以自底向上的方式计算出最优值;
(4)根据计算得到的最优值时得到的信息,构造最优解;
同时,问题的最优子结构性质也是该问题可用动态规划算法求解的显著特征,这里的最优子结构性质即指:问题的最优解也即代表着它的子问题有了最优解;
问题描述:
具体可参考:https://blog.csdn.net/liufeng_king/article/details/8497607
分析过程如下:
(1)分析最优子结构的性质:
(2)分析递归关系,以及利用自底向上的方式进行计算:
(3)获取最优值和最优解:
代码如下:
#ifndef MATRIX_CHAIN_H #define MATRIX_CHAIN_H void matrix_chain(int *p, int n, int **m, int **s); void traceback(int i, int j, int **s); #endif
#include <iostream> #include "matrix_chain.h" using namespace std; //利用动态规划算法获取最优值 void matrix_chain(int *p, int n, int **m, int **s) //p:各个矩阵的列数,n:矩阵个数,m:m[i:j]矩阵i到j的相乘次数,s:对应的分开位置 { for (int i = 0; i < n; i++) { m[i][i] = 0; } for (int r = 2; r <= n; r++) { for (int i = 0; i < n - r + 1; i++) { int j = i + r - 1; m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j]; s[i][j] = i; for (int k = i + 1; k < j; k++) { int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; if (t < m[i][j]) { m[i][j] = t; s[i][j] = k; } } } } } //利用s[i][j]获取最优解 void traceback(int i, int j, int **s) { if (i == j) return; traceback(i, s[i][j], s); traceback(s[i][j] + 1, j, s); cout << "Multiply A" << i << " , " << s[i][j]; cout << "and A" << (s[i][j] + 1) << " , " << j << endl; }
#include <iostream> #include "matrix_chain.h" using namespace std; int main(void) { int matrix_num = 0; //矩阵个数 cout << "请输入矩阵个数:" << endl; cin >> matrix_num; int **m = new int *[matrix_num]; for (int i = 0; i < matrix_num; i++) m[i] = new int[matrix_num]; int **s = new int *[matrix_num]; for (int i = 0; i < matrix_num; i++) s[i] = new int[matrix_num]; int *p = new int[matrix_num]; cout << "请输入各矩阵的列数:" << endl; for (int i = 0; i < matrix_num; i++) { cin >> p[i]; } matrix_chain(p, matrix_num, m, s); traceback(0, matrix_num - 1, s); system("pause"); return 1; }
可结合我的另一篇关于贪心算法的博客进行比较,了解这两者的区别;
(http://www.cnblogs.com/zf-blog/p/8674932.html)