您的位置:首页 > 其它

矩阵链乘-算法导论

2016-07-28 23:55 274 查看
问题描述:

给定n个矩阵的链,矩阵Ai的规模为pi−1pi,求完全括号化方案使得求解∏ni=1Ai所用标量乘法代价最少。

分析

问题具有最优子结构,即:

m[i,j] = min{m[i,k]+m[k,j]+pi−1pkpj

考虑用动态规划,接下来设计底层数据结构,显然应该用一个二维矩阵来自底向上的储存数据,现在考虑如何填充矩阵,以求解m[1,5]为例。



比如要填充m[1,5],显然需要知道第1行与第5列的全部值才能决定那一个接代价最低,可以验证填充任何一个下标为ij的位置都需要知道,i行j 列的数据。下面给出一种填充方案.



即对角线填充.

代码描述

/**
矩阵链乘
*/
#include<iostream>
#define INF 0x7fffffff
#define maxn 100
using namespace std;

int m[maxn][maxn],s[maxn][maxn];//最优解与分割点

void matrix_chain_order(int p[],int n)
{
for(int i= 1 ; i<=n ; ++i)m[i][i] = 0;

for(int l =2 ; l <=n ; ++l)//i,j的长度
{
for(int i=1 ; i<= n -l+1 ; ++i)
{
int j = i+l-1;//j-i +1 = l;
m[i][j] = INF;
for(int k=i ; k<j ; ++k)
{
int q = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];

if(q<m[i][j])
{
m[i][j] = q;
s[i][j] = k;//最优分割点
}
}
}
}
}


输出最优解

void print_optimal_parens(int i,int j)
{
if(i==j)printf("A%d",i);
else
{
printf("(");
print_optimal_parens( i, s[i][j]);//i,j之间的最优切割点
print_optimal_parens(s[i][j]+1, j);
printf(")");
}
}


测试

int main()
{

int p[] = {30,35,15,5,10,20,25};
int n = sizeof(p)/sizeof(p[0])-1;
matrix_chain_order( p, n);
print_optimal_parens(1, n);

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