zoukankan      html  css  js  c++  java
  • 动态规划_矩阵连乘问题

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

  • 相关阅读:
    洛谷p1017 进制转换(2000noip提高组)
    Personal Training of RDC
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Peterhof.
    Asia Hong Kong Regional Contest 2019
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Siberia
    XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix.
    XVIII Open Cup named after E.V. Pankratiev. GP of SPb
    卜题仓库
    2014 ACM-ICPC Vietnam National First Round
  • 原文地址:https://www.cnblogs.com/beatrice7/p/4149639.html
Copyright © 2011-2022 走看看