动态规划--矩阵连乘

#include<iostream>

using namespace std;
//无论括号怎么分这些连续相乘的矩阵,最后括号都可以归结到只有两对括号,把整个连乘的矩阵分成两部分
//          / 0    i==j
//m[i][j] =
//          \ min{ m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j] }  i<j, i<=k<j



//递归计算矩阵连乘
int liancheng(int i, int j, int *p, int **s) {
    if (i == j)
        return 0;
    int MIN = liancheng(i, i, p, s) + liancheng(i + 1, j, p, s) + p[i - 1] * p[i] * p[j];
    s[i][j] = i;
    for (int k = i+1; k < j; k++) {
        int rlt = liancheng(i, k, p, s) + liancheng(k+1, j, p, s) + p[i-1]*p[k]*p[j];
        if(rlt < MIN) {
            MIN = rlt;
            s[i][j] = k;
        }
    }
    return MIN;
}

int MatrixChain(int *p, int n, int **m, int **s) {
    for (int i = 1; i <= n; i++)
        m[i][i] = 0; //单个矩阵,计算次数为0
    for (int r = 2; r <= n; r++) { //代表几个矩阵连乘
        for (int i = 1; i <= n - r + 1; i++) { //i<=n-r+1是怎么得来的? i+r-1<=n
            int j = i + r - 1;//r个矩阵相乘,最后一个矩阵的坐标为j
            m[i][j] = m[i][i] + m[i + 1][j] + p[i - 1]*p[i]*p[j]; //把第一种m[i][j]的值当成是目前最小的,i也就是第一次k的位置
            s[i][j] = i;
            //为了求m[i][j]的所有情况中的最小值
            for (int k = i + 1; k < j; k++) { //因为上面已经计算了k=i的情况,所以继续往下计算的话,就计算k=i+1,这个地方的k一定是小于j的,不能等于j
                int temp = m[i][k] + m[k + 1][j] + p[i - 1]*p[k]*p[j];
                if (temp < m[i][j]) {
                    m[i][j] = temp;
                    s[i][j] = k;
                }
            }
        }
    }
    return m[1][n];
}

//求最优解,求出加括号的位置
void TraceBack(int i, int j, int **s)
{
    if(i == j) return;
    cout<<"a"<<i<<"~a"<<j<<" 把a"<<i<<"到a"<<s[i][j]<<"括起来, 把a"<<s[i][j]+1<<"到a"<<j<<"括起来"<<endl;
    TraceBack(i, s[i][j], s);
    TraceBack(s[i][j]+1, j, s);
}

//打印s数组,记录每个位置加括号的位置
void PrintS(int **s)
{
    for(int i=1; i<=6; i++) {
        for(int j=1; j<=6; j++) {
            cout<<s[i][j]<<" ";
        }
        cout<<endl;
    }
}

int main()
{
    //6个矩阵连乘
    int p[7] = { 30, 35, 15, 5, 10, 20, 25 };//用来存放每个矩阵的行和列数,第一个矩阵的行列为p[0][1], 第二个为p[1][2],第三
                                             //个为p[2][3],依此类推
    int **m; //传递二级指针的时候,这样做,直接int m[][],无法把m当作二级指针参数传进去
    m = (int **)new int[7];
    for (int i = 0; i < 7; i++) {
        m[i] = (int *)new int[7];
        
    }
    
    int **s;
    s = (int **)new int[7];
    for(int i=0; i<7; i++)
        s[i] = (int *)new int[7];
    
    cout << "递归结果: " << liancheng(1, 6, p, s) << endl;
    TraceBack(1, 6, s);
    for(int i=1; i<=6; i++)  //清空s数组
        for(int j=1; j<=6; j++)
            s[i][j] = 0;
    cout << "动态规划结果: "<<MatrixChain(p, 6, m, s) << endl;
    TraceBack(1, 6, s);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/haskei/article/details/78731581