动态规划_矩阵连乘问题

就会点儿C++,现在看见个问题就想封装封装,我是装运工么!

有关DP的一些列问题,这篇博客写的极好,戳http://www.cnblogs.com/chinazhangjie/archive/2010/11/16/1878400.html

动态规划要素

1.最优子结构性质:最优解包含着其子问题的最优解.

2.子问题的重叠性质:递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次.

3.备忘录方法:为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。

矩阵连乘问题

(以上是我截图上面链接里的博客内容)

刚开始就这里的P*P*P没明白, 其实就是自己数学sucks!

计算两个矩阵相乘,比如A1*A2,则总共要计算的乘法次数就是30 * 35 *15。那么把A1到A6从k位置分隔开来后,实际还是两个矩阵相乘啦,因为矩阵*矩阵还是矩阵,而且矩阵乘法满足结合律。所以这个P*P*P就是(A1~A6)被分割后,最后还得加上(A1~Ak)和 (Ak+1 ~ A6)这两大矩阵相乘的次数。就好比A1*A2, (i-1)对应30, k对应35,  j对应15。

而且实际代码里的两个二维数组m_和 s_都是7*7的矩阵,为的就是不用考虑恼人的下标0的问题。

实际是这样的,外面都多了一圈0.

代码如下(备忘录方法)

 1 #ifndef MATRIX_CHAIN_H_
 2 #define MATRIX_CHAIN_H_ 
 3 #include <iostream>
 4 #include <vector>
 5 
 6 class MatrixChain
 7 {
 8     public:
 9         MatrixChain(int nMatrix, int value[])
10             :nMatrix_(nMatrix), value_(value)
11         {}
12         void initBothMatrix();
13         int lookupChain(int i, int j);
14         void traceChain(int i, int j);
15         void printBest();
16         ~MatrixChain(){}
17 
18     private:
19         int* value_; //to store each Matrix's column and the first Matrix'srow
20         int nMatrix_; 
21         std::vector<std::vector<int> > m_; //to store min result between 'Matrix_i' and 'Matrix_j'
22         std::vector<std::vector<int> > s_; //to store the segment position, s[i][j]=k
23 
24 };
25 
26 #endif  /*MATRIX_CHAIN_H_*/
MatricChain.h
 1 #include <iostream>
 2 #include <vector>
 3 #include "MatrixChain.h"
 4 using namespace std;
 5 
 6 /* 将两个矩阵m_和s_都初始化为(nMatrix + 1) *(nMatrix + 1)大小的矩阵
 7  * 这便于以后的运算,从而无需考虑下标0的问题
 8  */
 9 void MatrixChain::initBothMatrix()
10 {
11     m_.resize(nMatrix_ + 1);
12     s_.resize(nMatrix_ + 1);
13     for(int i = 0; i <= nMatrix_; ++i)
14     {
15         m_[i].resize(nMatrix_ + 1);
16         s_[i].resize(nMatrix_ + 1);
17     }
18 
19     for(int i = 0; i <= nMatrix_; ++i)
20     {
21         for(int j = 0; j <= nMatrix_; ++j)
22         {
23             m_[i][j] = 0;
24             s_[i][j] = 0;
25         }
26     }
27 }
28 
29 
30 
31 int MatrixChain::lookupChain(int i, int j)
32 {
33     if(m_[i][j] > 0)
34         return m_[i][j];
35     if(i == j)
36         return 0;
37     int u = lookupChain(i, i) + lookupChain(i + 1, j) + *(value_+i-1) * *(value_+i) * *(value_+j);
38     s_[i][j] = i;
39 
40     for(int k = i + 1; k < j; ++k)
41     {
42         int t = lookupChain(i, k) + lookupChain(k + 1, j) + *(value_+i-1) * *(value_+k) * *(value_+j);
43         if(t < u)
44         {
45             u = t;
46             s_[i][j] = k;
47         }
48     }
49     m_[i][j] = u;
50     return u;
51 }
52 
53 
54 void MatrixChain::traceChain(int i, int j)
55 {
56     if(i == j){
57         cout << "A"<< i;
58     }else if(i+1 == j){
59         cout <<"(A" << i << "A" << j << ")";
60     }else{
61         cout << "(";
62         traceChain(i, s_[i][j]);
63         traceChain(s_[i][j] + 1, j);
64         cout << ")";
65     }
66 }
67 
68 //for test
69 void MatrixChain::printBest()
70 {
71     /*  
72     cout << "m_: " << endl;
73     for(int i = 0; i < nMatrix_; ++i)
74     {
75         for(int j = 0; j<= nMatrix_; ++j)
76             cout << m_[i][j] << " ";
77         cout << endl;
78     }
79     cout << "s_: " << endl;
80     for(int i = 0; i <= nMatrix_; ++i)
81     {
82         for(int j = 0; j<= nMatrix_; ++j)
83             cout << s_[i][j] << " ";
84         cout << endl;
85     }
86 
87     */
88     cout << "min multiply count: " << m_[1][nMatrix_] << endl;
89 }
MatrixChain.cpp
 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include "MatrixChain.h"
 5 using namespace std;
 6 
 7 const int L = 7;
 8 //A1 30*35 A2 35*15 A3 15*5 A4 5*10 A5 10*20 A6 20*25
 9 int main(int argc, const char *argv[])
10 {
11     //p中记录的是所有矩阵的行与最后一个矩阵的列对应的value
12     int p[L] = {30, 35, 15, 5, 10, 20, 25};
13     MatrixChain matrix_chain(L-1, p);
14     matrix_chain.initBothMatrix();
15     matrix_chain.lookupChain(1, L-1);
16     matrix_chain.printBest();
17     matrix_chain.traceChain(1, L-1);
18 
19     return 0;
20 }
testmain.cpp

 Tips:

1.维数组用vector<vector<> >这种方法还真是省心又好用,就是初始化的时候别忘了用.resize()设置下行列的大小,不然会出现越界之类的错误。

2.C++对齐输出两个矩阵:

#include <iomanip>

cout << setw(7) << m_[i][j]; //以宽度7对齐输出

原文地址:https://www.cnblogs.com/beatrice7/p/4149639.html