基于DP的矩阵连乘问题

当多个连续可乘矩阵做乘法时,选择正确的做乘顺序可以有效减少做乘法的次数,而选择的方法可以很容易的通过DP实现。

原理就是对于每一个所求矩阵,搜索所有可以相乘得到它的方法,比较它们的消耗,选取最小值作为采用的方法。

例如,给出矩阵A1(30*35) A2(35*15) A3(15*5) A4(5*10) A5(10*20) A6(20*25)

我们另m(i,j)表示从第i个矩阵乘到第j个矩阵,并用p[i]表示矩阵的边长,如p[0]=30,p[1]=35......

于是我们有:

若i==j m(i,j)=0

若i<j m(i,j)=min(m(i,k)+m(k+1,j)+p[i-1]*p[k]*p[j]),k=i,i+1,i+2...j-1(i<=k<j)

实际操作过程中,我们往往用数组来记录每一个我们已经计算过的m(i,j)来提高效率。

代码如下:

主算法:

#pragma once
#include <algorithm>
int matrix_p[MAX_V];
int m[MAX_V][MAX_V];
int matrix_V;

int matrix_mul(int i, int j)
{
    if (m[i][j] == INF)
    {
        for (int k = i;k < j;++k)
        {
            m[i][j] = std::min(m[i][j], matrix_mul(i, k) + matrix_mul(k + 1, j) + matrix_p[i - 1] * matrix_p[k] * matrix_p[j]);
        }
    }
    return m[i][j];
}

主程序:

void matrix_chain_test()
{
    cin >> matrix_V;
    for (int i = 0;i <= matrix_V;++i) cin >> matrix_p[i];
    for (int i = 0;i <= matrix_V;++i)
    {
        for (int j = 0;j <= matrix_V;++j)
        {
            m[i][j] = INF;
        }
        m[i][i] = 0;
    }
    int i, j;
    while (true)
    {
        cin >> i >> j;
        if (i == -1) break;
        cout << matrix_mul(i, j) << endl;
    }
}

PS:INF和MAX_V是两个很大的数,具体大家自己定就行。

posted @ 2016-07-11 16:28  CieloSun  阅读(448)  评论(0编辑  收藏  举报