• 动态规划_矩阵连乘问题


    就会点儿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对齐输出

  • 相关阅读:
    Java script基础 回顾
    Application、 session、iewstate,以及repeater 的commang用法
    Response、Request、QueryString,repeater添加,修改,删除数据
    Repeater 使用方法
    web form 复合控件
    weborm 简单控件
    WebForm开发基础
    Asp.Net 基础理论
    winform 进程,线程
    repeater使用
  • 原文地址:https://www.cnblogs.com/beatrice7/p/4149639.html
Copyright © 2020-2023  润新知