矩阵链乘法

来源:互联网 发布:温州市网络问政平台 编辑:程序博客网 时间:2024/06/05 16:35

矩阵链乘法
•给定一个由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 = jm[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] - 1for i ← 1 to n  do m[i, i] ← 0for 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] ← kreturn m and s
  1. 代码实现
    4.1 C语言版

pair.h file

#ifndef _PAIR_H#define _PAIR_H#ifdef __cplusplusextern "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. 运行结果:
    这里写图片描述
0 0
原创粉丝点击