矩阵链乘法

矩阵链乘法
•给定一个由n个矩阵构成矩阵序列(链)<A1, A2, ..., An>,要将它们相乘(假定它们按此序列是乘法相容的:Ai是pi-1×pi矩阵,而Ai+1是pi×pi+1矩阵),计算积:

           A1A2 ... An

•只要对此序列加上括号,确定运算顺序,就可以算得它们的积。矩阵链的积称为是完全加括号的,若它或是单一的矩阵,或是两个完全加括号的矩阵子链之积,并用一对括号括起来。

1.问题的理解与描述
•输入:数组<p0, p1, …, pn>,其中pi-1和pi分别是矩阵Ai的行数和列数,i=1, 2, …, n。
•输出:计算积A1A2 … An的最优完全加括号形式。
2.最优子结构
•假定Ai Ai+1… Aj的最优完全加括号在Ak及Ak+1之间分裂。则该加括号的“前缀”子链Ai Ai+1… Ak在Ai Ai+1… A j的此最优加括号中的完全加括号必为Ai Ai+1… Ak的最优加括号。
•设m[i, j]为计算矩阵所需的最少标量乘法次数,根据上面的最优子结构的讨论,我们有:

0    如果i = j
m[i,j] = │
          └ min(i≤k<j) {m[i,k] + m[k+1,j] + Ai.row*Ak.col*Aj.col}  如果ij

3.算法的伪代码描述

MATRIX-CHAIN-ORDER(p)
n ← length[p] - 1
for i ← 1 to n
  do m[i, i] ← 0
for l ← 2 to n //l 是矩阵链的长度
  do for i ← 1 to n - l + 1
     do j ← i + l - 1
        m[i, j] ← ∞
        for k ← i to j - 1
            do q ← m[i, k] + m[k + 1, j] + pi-1 pkpj
               if q < m[i, j]
                  then m[i, j] ← q
                  s[i, j] ← k
return m and s
  1. 代码实现
    4.1 C语言版

pair.h file

#ifndef _PAIR_H
#define _PAIR_H
#ifdef __cplusplus
extern "C"  //告诉编译器{   }内部是用C写成的文件,请用C的方式来连接他们
{
#endif
    typedef struct 
    {
        void* first;
        void* second;
    }pair;
    pair make_pair(void*f, void*d);
    pair matrixChainOrder(int *p, int n);
    void printOptimalParens(int *s, int i, int j, int n);
#ifdef __cplusplus
}
#endif

#endif

pair.c file

#include <stdlib.h>
#include <stdio.h>
#include<limits.h>
#include "pair.h"

pair make_pair(void*f, void*d)
{
    pair p = { f, d };
    return p;
}
pair matrixChainOrder(int *p, int n)
{
    int i, l, j, k, q;
    int *m = (int*)malloc((n + 1)*(n + 1)*sizeof(int));//m 存储最小标量乘法次数
    int *s = (int*)malloc((n + 1)*(n + 1)*sizeof(int));//s:存储最优解表格
    for (i = 0; i <= n; i++)
        m[i*(n + 1) + i] = 0;//m[i][i]=0
    for (l = 2; l <= n ; l++)//l 为子矩阵链的长度
        for (i = 1; i <= n - l + 1;i++)
        {
            j = i + l - 1;
            m[i*(n + 1) + j] = INT_MAX;//m[i,j]=∞
            for (k = i; k <= j - 1;k++)
            {
                q = m[i*(n + 1) + k] + m[(k + 1)*(n + 1) + j] + p[i - 1] * p[k] * p[j];
                if (q<m[i*(n+1)+j])
                {
                    m[i*(n + 1) + j] = q;
                    s[i*(n + 1) + j] = k;
                }
            }
        }
    return make_pair(m, s);
}
void printOptimalParens(int *s, int i, int j, int n)
{
    if (i == j)
        printf("A%d",i);
    else
    {
        printf("(");
        printOptimalParens(s, i, s[i*(n + 1) + j],n);
        printOptimalParens(s, s[i*(n + 1) + j] + 1, j,n);
        printf(")");
    }
}

main.c file

#include <stdio.h>
#include <stdlib.h>
#include "pair.h"
int main(int argc, char ** argv)
{
    int p[] = { 30, 35, 15, 5, 10, 20, 25 };
    int *s, *m;
    pair r = matrixChainOrder(p, 6);
    m = (int*)r.first;
    s = (int*)r.second;
    printOptimalParens(s, 1, 6, 6);
    printf("\n the min muilty times is: %d \n", m[13]);
    free(s);
    free(m);
    system("pause");
    return (EXIT_SUCCESS);
}

4.2 C++版

matrixchain.cpp fiel

#include "stdafx.h"
#include "matrixchain.h"
#include <climits>
pair<int*, int*>matrixChainOrder(int*p, int n)
{
    long i, l, j, k, q;
    int *m = new int[(n + 1)*(n + 1)];
    int *s = new int[(n + 1)*(n + 1)];
    for (i = 1; i <= n; i++)
        m[i*(n + 1) + i] = 0;//m[i,i]=0
    for (l = 2; l <= n; l++)
        for (i = 1; i <= n - l + 1;i++)
        {
            j = i + l - 1;
            m[i*(n + 1) + j] = INT_MAX;
            for (k = i; k <= j - 1;k++)
            {
                q = m[i*(n + 1) + k] + m[(k + 1)*(n + 1) + j] + p[i - 1] * p[k] * p[j];
                if (q<m[i*(n+1)+j])
                {
                    m[i*(n + 1) + j] = q;
                    s[i*(n + 1) + j] = k;
                }
            }
        }
    return make_pair(m, s);
}
void printOptimalParens(int *s, int i, int j, int n)
{
    if (i == j)
        cout << 'A' << i;
    else
    {
        cout << '(';
        printOptimalParens(s, i, s[i*(n + 1) + j], n);
        printOptimalParens(s, s[i*(n + 1) + j] + 1, j, n);
        cout << ')';
    }
}

matrixchain.h fiel

#ifndef _MATRIXCHAIN_H
#define _MATRIXCHAIN_H
#include <iostream>
using namespace std;
pair<int*, int*> matrixChainOrder(int*p, int n);
void printOptimalParens(int *s, int i, int j, int n);
#endif

main.cpp file

#include "stdafx.h"
#include "matrixchain.h"

int _tmain(int argc, _TCHAR* argv[])
{
    int p[] = { 30, 35, 15, 5, 10, 20, 25 };
    int *s, *m;

    pair<int*,int*> r = matrixChainOrder(p, 6);

    m = r.first;
    s = r.second;
    printOptimalParens(s, 1, 6, 6);
    cout << endl << m[13] << endl;
    delete[]s;
    delete[]m;
    system("pause");
    return 0;
}

  1. 运行结果:
    这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值