矩阵链乘-算法导论
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 列的数据。下面给出一种填充方案.
即对角线填充.
代码描述
输出最优解
测试
给定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; }
相关文章推荐
- java算法导论之FloydWarshall算法实现代码
- MIT Introduction to Algorithms 学习笔记(一)
- MIT Introduction to Algorithms 学习笔记(二)
- MIT Introduction to Algorithms 学习笔记(三)
- MIT Introduction to Algorithms 学习笔记(四)
- MIT Introduction to Algorithms 学习笔记(五)
- MIT Introduction to Algorithms 学习笔记(六)
- MIT Introduction to Algorithms 学习笔记(七)
- MIT Introduction to Algorithms 学习笔记(八)
- MIT Introduction to Algorithms 学习笔记(九)
- MIT Introduction to Algorithms 学习笔记(十)
- 堆排序/优先级队列
- 插入排序
- Red-Black Tree 的Java实现
- 逆序对
- 算法导论之堆
- 算法基础1—插入排序
- LCS 最长公共子序列
- 使用Java完成《算法导论》习题2.2-2
- 使用Java完成《算法导论》习题2.3-2