矩阵连乘问题

多个矩阵连乘,给这样的矩阵序列加括号,使乘法的计算次数最小。使用的是动态规划的思想。

#include 
#include 
#include 
using namespace std;

void MatrixChain(int n, int *p, int **m, int **s){
    /*
    找到矩阵链乘法需要的最小乘法次数,以及划分的方式
    :param n: 矩阵A的个数
    :param p: 存放矩阵维度的数组,有n+1个元素
    :param m: m[i, j]存放矩阵i到矩阵j
              这个矩阵序列在最优划分下的乘法次数

    :param s: s[i, j]存放矩阵i到矩阵j
              这个矩阵序列在最优划分下时,断开的位置k
              在位置k断开,代表的是将A_k和A_(k+1)分开
    m, s下标从1开始
    m[i][j] = 0, i=j
    m[i][j] = min{m[i][k], m[k+1][j]+p[i-1]*p[k]p[j]} for k /in [i,j), i
    for(int i = 1; i <= n; ++i) m[i][i] = 0;
    for(int r = 1; r < n; ++r){  // r是间隔,计算m[i][i+r]
        for(int i = 1; i <= n-r; ++i){
            int j = i+r;
            m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j]; // 把i, i+1之间断开
            s[i][j] = i;
            for(int k = i+1; k < j; ++k){  // 划分点从k枚举到j-1
                int tmp = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
                if(tmp < m[i][j]) {
                    m[i][j] = tmp;
                    s[i][j] = k;
                }
            }
        }
    }
}

string int2str(int n){
    stringstream ss;
    ss << n;
    string res;
    ss >> res;
    return res;
}
string Traceback(int i, int j, int **s){
    if(i == j) return "A"+int2str(i);
    string left = Traceback(i, s[i][j], s);
    string right = Traceback(s[i][j]+1, j, s);
    return '('+left+right+')';
}
int main(){
    const int n = 6;
    int *p = new int[n+1];
    p[0]=30;p[1]=35;p[2]=15;p[3]=5;p[4]=10;p[5]=20;p[6]=25;
    int **m = new int*[n+1], **s = new int*[n+1];
    for (int i = 0; i <= n; ++i){
        m[i] = new int[n+1]();  // 每个元素初始化为0
        s[i] = new int[n+1]();
    }
    MatrixChain(n, p, m, s);
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= n; ++j){
            cout << m[i][j] << ' ';
        } cout << endl;
    }
    cout << "The minimal number of multiply is : " << m[1][n] << endl;
    cout << "The order of multiply is :" << Traceback(1, n, s) << endl;
    return 0;
}

你可能感兴趣的:(数据结构,算法)