您的位置:首页 > 其它

动态规划——矩阵链乘法

2008-02-01 14:22 281 查看
矩阵链乘法
问题描述:给定n个矩阵构成的一个链<A[1], A[2], ... , A
>,其中i = 1, 2, ... , n,矩阵A[i]的维数为p[i-1]*p[i],对乘积A[1]A[2]...A
以一种最小化标量乘法次数的方式进行加全部括号。
步骤1:最优加全部括号的结构
用记号A[i..j]表示乘积A[i]A[i+1]...A[j]求值的结果,其中i <= j。假设A[i]A[i+1]...A[j]的一个最优加全部括号把乘积在A[k]和A[k+1]之间分开,则对A[i]A[i+1]...A[j]最优加全部括号的“前缀”子链A[i]A[i+1]...A[k]的加全部括号必须是A[i]A[i+1]...A[k]的一个最优加全部括号。
步骤2:一个递归解
设m[i][j]为计算矩阵A[i..j]所需的标量乘法运算次数的最小值;对整个问题,计算A[1..n]的最小代价就是m[1]

假设最优加全部括号将乘积A[i]A[i+1]...A[j]从A[k]和A[k+1]之间分开,i <= k < j。则:
m[i][j] = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
关于对乘积A[i]A[i+1]...A[j]加全部括号的最小代价的递归定义为:
m[i][j] = 0 if i == j
m[i][j] = min(i<=k<j){m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]} if i < j
步骤3:计算最优代价
用迭代自底向上的表格法来计算最优代价。
步骤4:构造一个最优解
利用保存在表格s

内的、经过计算的信息来构造一个最优解。按最优方式计算A[1..n]时,最终矩阵相乘次序是A[1..s[1]
]A[a[1]
+1..n]。之前的乘法可以递归地进行。

MatrixChainMain.c


#include <stdio.h>


#include <limits.h>


#define LENGTH 6






/**//*


*p[i]:矩阵Ai的列数或Ai-1的行数


*m[i][j]:纪录Ai - Aj的矩阵连乘的最小代价


*s[i][j]:纪录Ai - Aj之间得到最小连乘代价时的分割点


*/


void MatrixChainOrder(int p[], int m[][LENGTH], int s[][LENGTH])




...{


int i, j, k, len, q;




for(i=0; i<LENGTH; i++)


m[i][i] = 0;


for(len=2; len<=LENGTH; len++) //len为矩阵链的长度




...{


for(i=0; i<(LENGTH-len+1); i++)




...{


j = i + len - 1;


m[i][j] = INT_MAX;


//计算Ai - Aj最优代价


for(k=i; k<j; k++)




...{


q = m[i][k] + m[k+1][j] +p[i]*p[k+1]*p[j+1];


if(q < m[i][j])




...{


m[i][j] = q;


s[i][j] = k;


}


}


}


}


}




void PrintOptimalParens(int s[][LENGTH], int i, int j)




...{


if(i == j)


printf("A%d", i);


else




...{


printf("(");


PrintOptimalParens(s, i, s[i][j]);


PrintOptimalParens(s, s[i][j]+1, j);


printf(")");


}


}




int main(int argc, char **argv)




...{




int p[LENGTH+1] = ...{30, 35, 15, 5, 10, 20, 25};


int m[LENGTH][LENGTH];


int s[LENGTH][LENGTH];




MatrixChainOrder(p, m, s);


PrintOptimalParens(s, 0, LENGTH-1);


printf(" ");




return 0;


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: